Here is my problem.
I am using trial version of IBM MQ V7.1. I have created a queue manager MYQM, a channel MY_SVRCONN with MCA User Id abc. I have provided user abc to access MYQM. I am trying to put a message into the queue Q1. But while getting the queue connection i am getting below exception.
com.ibm.msg.client.jms.DetailedJMSSecurityException: JMSWMQ2013: The security authentication was not valid that was supplied for QueueManager 'MYQM' with connection mode 'Client' and host name '(1500)'.
Please check if the supplied username and password are correct on the QueueManager to which you are connecting.
I have used below command to allow user abc to access MYQM.
[mqm#localhost ~]$ setmqaut -m MYQM -t qmgr -p abc +connect
The setmqaut command completed successfully.
Here is my Java program
public class MqPut
{
public static void main(String[] args)
{
sendMsg("Sample Message");
}
public static void sendMsg(String msg)
{
MQQueueConnectionFactory connectionFactory = null;
QueueConnection queueConn = null;
QueueSession queueSession = null;
QueueSender queueSender = null;
TextMessage message = null;
try
{
connectionFactory = new MQQueueConnectionFactory();
connectionFactory.setHostName(<MQ SERVER IP>);
connectionFactory.setPort(1500);
connectionFactory.setTransportType(WMQConstants.WMQ_CLIENT_NONJMS_MQ);
connectionFactory.setQueueManager("MYQM");
connectionFactory.setChannel("MY_SVRCONN");
queueConn = connectionFactory.createQueueConnection("abc","password");
queueSession = queueConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queueSender = queueSession.createSender(queueSession.createQueue("Q"));
queueSender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
message = queueSession.createTextMessage(msg);
queueSender.send(message);
queueConn.close();
}
catch (Exception je)
{
je.printStackTrace();
}
}
}
I have tried with WebSphere 7, configuring JMS Q connection factory without user id: MQRC_NOT_AUTHORIZED, but still my problem persist. I am not getting what I am doing wrong. Any help is appreciated.
EDIT
User abc is not part of mqm group
Have you set chlauth (channel authentication) for the user on the svrconn channel? Channel authentication is new from MQ 7.1 onwards. The password validation is available from MQ 8 only. Basically you need to allow the remote connections from your client IP on the qmgr svrconn channel.
try in the mqsc console
SET CHLAUTH(MY_SVRCONN) TYPE(ADDRESSMAP) ADDRESS(ip of the client machine) USERSRC(CHANNEL)
If this doesnt work, check the qmgr log. It should exactly say what is causing the 2035.
A good technote is found here http://www-01.ibm.com/support/docview.wss?uid=swg21577137
Morag's really useful blog https://www.ibm.com/developerworks/community/blogs/aimsupport/entry/blocked_by_chlauth_why?lang=en
In a development environment (WMQ 8.0), I prefer to modify the authorization so that it is optional.
ALTER AUTHINFO(SYSTEM.DEFAULT.AUTHINFO.IDPWOS) AUTHTYPE(IDPWOS) CHCKCLNT(OPTIONAL)
REFRESH SECURITY TYPE(CONNAUTH)
(Disabling this feature is not recommended for production queue managers due to security implications.)
In WMQ 7.1, it's possible to set channel authorization to be disabled, but that does not appear to work on WMQ 8.0
ALTER QMGR CHLAUTH(DISABLED)
Whenever you get any error back from a queue manager, remember that you should always look in the queue manager AMQERR01.LOG for a more detailed explanation. This is especially true for any security related error, since only a single error code - MQRC_NOT_AUTHORIZED (2035) - which is translated into JMS Exception JMSWMQ2013 - is returned to the application so as to not give away the details why to any potential hacker. You must always look at the queue manager error log for the details.
Related
I set up a connection with Weblogic IBM Webpsphere MQ through JMS with using a secure channel using SSL.
My application on Weblogic received message from MQ.
Sending answer to reply queue.
The response header is present MQMD, it fills java. In parameter Persistence JMS send value "1". Other system need to received value "0" at Persistence. How to set this parameter to java?
I guess that parameter is javax.jms.deliverymode. But how to set it i don't know.
Anyway thank you for help.
The corresponding property on JMS is the delivery mode (Int parameter to be set) to set Persistent and non persistent messages.
You can refer this URL from IBM for details
You should try like this:
public String sendMessage(ConnectionFactory connectionFactory,
Destination destination,
Destination jmsReplyTo,
CorrelationType correlationType,
CallOptions<String> callOptions,
String rqUid,
JMSAbstract transport) throws JMSException {
Connection connection = null;
Session session = null;
MessageProducer producer = null;
try {
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(destination);
// Set JMS DeliverMode (1/2)
producer.setDeliveryMode(1);
// create message
Message message = createTextMessage(session, jmsReplyTo, correlationType, callOptions, rqUid, transport);
// send message
producer.send(message);
return correlationType.getCorrelationId(message);
} finally {
closeResource(connection, session, null, producer, rqUid);
}
}
It`s just a java example. Also you can set persistence flag in Queue configuration in IBM WebSphere. I mean MQQueue have method setPersistence. If you using IBM java objects in your project, you can set persistence by calling that method:
MQQueue mqQueue = new MQQueue("QueueName");
mqQueue.setPersistence(1);
I The answer of 0x5a4d is ok but better to use this like IBM best practices
//Persistentmode = 1
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
//Persistentmode = 2
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
I have a IBM MQ version 7.5 installation in windows 7. I have created a queue manager, channel and listener using the following commands.
//CREATE THE QUEUE MANAGER
crtmqm.exe PG3RT1
//START THE QUEUE MANAGER AS INTERACTIVE
strmqm.exe -si PG3RT1
//CONNECT AS SCRIPT CONSOLE
runmqsc.exe PG3RT1
//CREATE THE CHANNEL TO APPLICATION CONNECTIVITY
DEFINE CHANNEL(PG3RT1.CHANNEL) CHLTYPE(SVRCONN) TRPTYPE(TCP)
//CREATE THE LISTENER
DEFINE LISTENER(LISTENER.PG3RT1) TRPTYPE(TCP) PORT(1414)
//START THE LISTENER
START LISTENER(LISTENER.PG3RT1)
Now i am trying to connect to the Queue Manager using following java client.
connection is rejected with the following error.
15:06:52.175 [localhost-startStop-1] ERROR c.b.c.s.s.m.MQUtil - MQJE001: Completion Code '2', Reason '2035'.
com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2035'.
at com.ibm.mq.MQManagedConnectionJ11.<init>(MQManagedConnectionJ11.java:230)
at com.ibm.mq.MQClientManagedConnectionFactoryJ11._createManagedConnection(MQClientManagedConnectionFactoryJ11.java:553)
at com.ibm.mq.MQClientManagedConnectionFactoryJ11.createManagedConnection(MQClientManagedConnectionFactoryJ11.java:593)
at com.ibm.mq.StoredManagedConnection.<init>(StoredManagedConnection.java:96)
at com.ibm.mq.MQSimpleConnectionManager.allocateConnection(MQSimpleConnectionManager.java:198)
at com.ibm.mq.MQQueueManagerFactory.obtainBaseMQQueueManager(MQQueueManagerFactory.java:893)
at com.ibm.mq.MQQueueManagerFactory.procure(MQQueueManagerFactory.java:780)
at com.ibm.mq.MQQueueManagerFactory.constructQueueManager(MQQueueManagerFactory.java:729)
at com.ibm.mq.MQQueueManagerFactory.createQueueManager(MQQueueManagerFactory.java:177)
at com.ibm.mq.MQQueueManager.<init>(MQQueueManager.java:745)
at com.bcs.cas.sach.simulator.mq.MQUtil.init(MQUtil.java:52)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
Can anyone advise why the connection is failing.
Do i need to enable remote administration on the queue manager?
Following is the code fragement i used for connection
public void init(){
MQEnvironment.hostname = hostName;
MQEnvironment.port = Integer.valueOf(port);
MQEnvironment.channel = serverChannelName;
MQEnvironment.properties.put(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES);
LOGGER.info("queueManagerName: " + queueManagerName);
LOGGER.info("hostName: " + hostName);
LOGGER.info("serverChannelName: " + serverChannelName);
LOGGER.info("port: " + port);
//initialize the connection pool
MQPoolToken token = MQEnvironment.addConnectionPoolToken();
try {
mqQueueManager = new MQQueueManager(queueManagerName, MQEnvironment.properties);
LOGGER.info("mqQueueManager: " + mqQueueManager);
} catch (MQException e) {
LOGGER.error(e.getMessage(), e);
}
}
MQRC 2035 is MQRC_NOT_AUTHORIZED. The reason this was returned can be found in the AMQERR log on the queue manager.
As CHLAUTH hasn't been configured, and is on by default, I expect you're not able to connect as you're not passing the CHLAUTH rules.
It is quite likely that this is an authorization issue. The easiest is to look at the return code and interpret
mqrc 2035 returns MQRC_NOT_AUTHORIZED
One of the reasons for it could be permissions. This can be resolved either by setting the right privilges on the QueueManager (setmqaut) , then on the channel enable the user with you are connecting to MQ to authorize as explained here . Post this you can use the code to connect by adding userId to the MQEnvironment and go
You can also refer this technote for information.
We are using clearing the authentication setting on manager by runmqsc:
SET CHLAUTH('CNL_NAME') TYPE(BLOCKUSER) USERLIST(ALLOWANY)
ALTER QMGR CONNAUTH(' ')
REFRESH SECURITY TYPE(CONNAUTH)
in case of development. Or proper setting of credentials:
QueueConnectionFactory.createQueueConnection(props.get(PROP.USER), props.get(PROP.PASSWD));
for JMS or:
...
MQEnvironment.userID = uid;
MQEnvironment.password = passwd;
new MQQueueManager(isQueueMgr);
for native com.ibm.mq.MQQueueManager.
I am new to MQ and JNDI and I looking for some simple sample Java code that resolves my WAS JMS configuration and can write to and read from two Message Queues.
specifically I would like JAVA code to:
run code on IBM WebSphere Application Server Network Deployment (WAS ND 8.5.5)
write to, and read from, 2 IBM Integration Bus (IIB) Message Queues on an external system
In WAS I configured JMS resources as follows:
for the connection factory - gave it a JNDI name of "jms/MQCONN.FACTORY"
for the queue #1 - gave it a JNDI name of "jms/MQUEUE1.DEST"
for the queue #2 - gave is a JNDI name of "jms/MQUEUE2.DEST"
I set up JAAS - J2C authentication data credentials.
Note: I was unable to test the connection to MQ for connection factory, because the security settings are added to after the wizard completes and the you can only test from the wizard. I believe the WAS configuration is correct including the credentials.
I especially do not understand how to code the JNDI part (i.e. How to store the environment variable that tells JNDI which initial context to use, and where to find the provider.)
Grateful for any assistance!
Sibyl , Once you have configured these Managed Objects (QueueConnectionFactory . Queue) , you should be able to lookup these from code that you can deploy on the application server.
You will have to get
a) InitialContext (when you deploy a ear on the server , you can use the default constructor)
b) Lookup queue connection factory (context.lookup(xxx))
c) Lookup queue (context.lookup(yyyy))
d) Create a message producer
e) Create a Queue Session , text message and send the message directly
You can get some more idea here (http://www.webspheretools.com/sites/webspheretools.nsf/docs/Creating%20a%20Queue%20Connection%20Factory%20and%20Queue%20for%20connectivity%20to%20MQ)
Basically post configuration it is a lot of Boilerplate JMS coding
Here is little help for you.
You don't need to provide extra configuration after creating resources in WAS.
Queue myQueue;
QueueConnectionFactory myQueueFactory;
QueueConnection connection = null;
QueueSession session = null;
try{
InitialContext jndi = new InitialContext();
myQueueFactory = (QueueConnectionFactory) jndi.lookup("jms/MQCONN.FACTORY");
myQueue = (Queue) jndi.lookup("jms/MQUEUE1.DEST");
connection=myQueueFactory.createQueueConnection();
session = connection.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
QueueSender sender = session.createSender(myQueue);
connection.start();
TextMessage textMessage = session.createTextMessage(event);
textMessage.setStringProperty("messageType", "file");
sender.send(textMessage);
sender.close();
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
} catch (JMSException e) {
e.printStackTrace();
}
How can I check whether a queue exists on a JMS server using the Java API? I don't want to send or receive any data to the queue for now, just verify that the queue exists. Also, the queue may be empty.
Here is my code sample. I have removed the error handling for simplicity.
Connection connection = null;
Session session = null;
connection = factory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//I was hoping this next line would throw an exception if the queue does not exist
Queue queue = session.createQueue(queueName);
My JMS server is TIBCO EMS. I'm hoping for a solution that works on versions 5-7.
Solution
I followed the recommendation in the accepted answer but created a browser instead. The following line threw an exception as desired:
QueueBrowser browser = session.createBrowser(queue);
This is dependent on the provider, but you wont know in most cases until you create the session type, such as session.createConsumer. Simply creating a consumer this way will not consume any messages until you do a receive. And it is here the behavior may change from provider to provider and configuration of the server.
For example with ActiveMQ, assuming there are no permissions blocking the user you are connecting with, the queue is created automatically when you create the session type.
With WebSphere MQ, the queue has to be defined by an admin. If it does not exist, the queue manager will return an exception with a reason code of 2085 (UNKNOWN_OBJECT_NAME).
Outside of this, you'd need to see if the particular provider had a way to access a list of queues. Using the above examples, ActiveMQ you can get the list of queues using JMX, with WebSphere MQ, you can do this if you have permissions to send PCF commands to the queue manager.
Try creating a consumer or producer off the Session passing in the queue object you just created:
session.createConsumer(queue);
This should throw an InvalidDestinationException if the queue (or topic) does not exist.
I'm very new to ibm mq, I find out the documents or books related to mb are so few, the only one I found is 'WebSphere MQ Using Java' written in 2004. But the real world has changed a lot.
I installed and verified mq server 7.5 on redhat linux 64 bit successfully according to this
I also created queue manager myqm1, queue LQ.TEST, channel JAVA.CHANNEL and did some test through command lines on server to ensure they work well. However when I installed a mq client on windows xp and wrote below java code, it always throw a exception:com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2035'
my code:
import com.ibm.mq.*; import com.ibm.mq.constants.MQConstants;
/** * Simple example program */ public class MQSample {
// code identifier
static final String sccsid = "#(#) MQMBID sn=p000-L120604 su=_H-IvIK4nEeGko6IWl3MDhA pn=MQJavaSamples/wmqjava/MQSample.java";
// define the name of the QueueManager
private static final String qManager = "myqm1";
// and define the name of the Queue
private static final String qName = "LQ.TEST";
/**
* Main entry point
*
* #param args - command line arguments (ignored)
*/
public static void main(String args[]) {
try {
MQEnvironment.hostname = "58.2.221.196";
MQEnvironment.channel = "JAVA.CHANNEL";
MQEnvironment.port = 1414;
MQEnvironment.properties.put(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES);
MQEnvironment.userID = "mqm";
MQEnvironment.password = "mqm";
MQEnvironment.CCSID = 1208;
// Create a connection to the QueueManager
System.out.println("Connecting to queue manager: " + qManager);
MQQueueManager qMgr = new MQQueueManager(qManager);
// Set up the options on the queue we wish to open
int openOptions = MQConstants.MQOO_INPUT_AS_Q_DEF | MQConstants.MQOO_OUTPUT;
// Now specify the queue that we wish to open and the open options
System.out.println("Accessing queue: " + qName);
MQQueue queue = qMgr.accessQueue(qName, openOptions);
// Define a simple WebSphere MQ Message ...
MQMessage msg = new MQMessage();
// ... and write some text in UTF8 format
msg.writeUTF("Hello, World!");
// Specify the default put message options
MQPutMessageOptions pmo = new MQPutMessageOptions();
// Put the message to the queue
System.out.println("Sending a message...");
queue.put(msg, pmo);
// Now get the message back again. First define a WebSphere MQ
// message
// to receive the data
MQMessage rcvMessage = new MQMessage();
// Specify default get message options
MQGetMessageOptions gmo = new MQGetMessageOptions();
// Get the message off the queue.
System.out.println("...and getting the message back again");
queue.get(rcvMessage, gmo);
// And display the message text...
String msgText = rcvMessage.readUTF();
System.out.println("The message is: " + msgText);
// Close the queue
System.out.println("Closing the queue");
queue.close();
// Disconnect from the QueueManager
System.out.println("Disconnecting from the Queue Manager");
qMgr.disconnect();
System.out.println("Done!");
} catch (MQException ex) {
ex.printStackTrace();
System.out.println("A WebSphere MQ Error occured : Completion Code " + ex.completionCode
+ " Reason Code " + ex.reasonCode);
} catch (java.io.IOException ex) {
System.out.println("An IOException occured whilst writing to the message buffer: " + ex);
}
return;
} }
Can anybody throw a light to me on that? I'm totally down.
To expand on Shashi's answer, since WMQ V7.1 the default CHLAUTH rules block all access on all SVRCONN channels and they block administrative access on all SVRCONN channels. If you really want to connect to JAVA.CHANNEL as mqm then you will need to override both of these behaviors.
If you are actually willing to allow remote, unauthenticated connections to the QMgr with an administrative user ID, then you have the option of disabling CHLAUTH rules altogether. You can do this by issuing the ALTER QMGR CHLAUTH(DISABLED) command in runmqsc however this is HIGHLY discouraged because it leaves the QMgr open to anonymous remote code execution using the WMQ administrative user ID. This is, however, what you appear to be trying to do.
The recommended approach would be to use an ID that is not administrative. For example, if you made an ID called mquser with a private group also called mquser then you could grant it rights to connect and inquire on the QMgr and to open the designated queue for put, get, browse and inquire. Since the ID is not administrative, it would be relatively safe to use on unauthenticated channels. You could change your code to specify the ID as mquser instead of mqm and then use a CHLAUTH rule to allow the connection. For example:
SET CHLAUTH('JAVA.CHANNEL') TYPE(USERMAP) +
CLNTUSER('mquser') USERSRC(MAP) +
MCAUSER('mquser') ACTION(ADD)
The above rule tells the QMgr "when you see a connection from the mquser ID on JAVA.CHANNEL, then set MCAUSER to mquser and allow the connection."
When you grant permissions, remember to grant them on the group and not the user. For example, if using setmqaut use the -g option and not the -p option. If there are any issues with authorization errors, you can sort these out easily using event messages. First, enable events using the ALTER QMGR AUTHOREV(ENABLED). This will cause the QMgr to emit an event message into the SYSTEM.ADMIN.QMGR.EVENT queue. You can use SupportPac MH05 or SupportPac MS0P to parse the event messages. For any given authorization event the message tells you the ID that requested access, the API call (connect, open, close etc.), the object the call was made against and the exact options that were used.
Prior to WMQ V7.1, WebSphere MQ allowed all remote connections, even anonymous, administrative ones. Although this allowed you to connect easily, in today's more hostile network environment the ability to remotely and anonymously execute code on the QMgr's host server is seen as an unacceptable security risk. So now a new QMgr is set to not allow any remote administrative access by default. As the administrator this requires you to explicitly disable security to get the old behavior or to explicitly provision secure access.
In MQ v7.5, by default access to queue manager is blocked. You need to create channel authentication records for the channel you created, JAVA.CHANNEL to allow user to access queue manager. Please follow this link for more details on Channel Authentication Records