work with IBM MQ from Java - java

I have a problem with connection in IBM MQ from java
this code
val cf: MQQueueConnectionFactory?
var mqConnection: QueueConnection? = null
var session: QueueSession? = null
var sender: QueueSender? = null
var value = ""
try {
cf = MQQueueConnectionFactory()
cf.hostName = host
cf.port = port
cf.queueManager = queueManager
cf.transportType = transport
cf.channel = channelName
cf.clientReconnectOptions = WMQConstants.WMQ_CLIENT_RECONNECT_Q_MGR
cf.clientReconnectTimeout = 3600
mqConnection = cf.createQueueConnection()
drops exception "JMSCMQ0001: WebSphere MQ call failed with compcode
'2' ('MQCC_FAILED') reason '2035' ('MQRC_NOT_AUTHORIZED')"
when I try create connection cf.createQueueConnection()
I don't understand what is a problem.
I use ibmmq lib 9.0.2.0 version, but this code doesn't work with 7.5.0.1 version too

MQRC 2035 means the user doesn't have the appropriate authorities to connect to the queue manager. The reason can be found in the AMQERR*.log in the queue manager errors directory. CHLAUTH is enabled by default. You need to add CHLAUTH rules. Following link provides details on create/modify CHLAUTH
IBM MQ 7.5.0 > WebSphere MQ > Reference > Administration reference > MQSC reference > The MQSC commands > SET CHLAUTH
If you want more details on CHLAUTH then go through the following link:
CHLAUTH Made Simple: Common Scenarios and Examples and How to Verify them with RUNCHECK

mqConnection = cf.createQueueConnection()
You should/need to pass the UserId and Password for the connection.
i.e.
mqConnection = cf.createQueueConnection("myUserId", "mypwd");

Related

Connecting to an MQ with Jmeter

I've been assigned the task of using Apache Jmeter to connect to an MQ. Unfortunately, I'm not the admin of the MQ, and all my attempts to get more information about it have gotten me nowhere. What I have now is a queue name (call it q), a queue manager (its name, anyway; call it v), a host (w), a port (x), a channel (y), a user (z), and a test message I'm supposed to send across. The object of the game is straightforward: send the test message from Apache Jmeter to the MQ (after which I'll ask the admins whether the message went through or not). In other words, I need help figuring out what to do with Jmeter.
The MQ is version 8.0.0.4. I already have Jmeter installed, so I don't need advice on that (unless there's some special way it should have been installed for this task).
The links provided in this question's answer didn't get me very far. They seemed largely unrelated to what I was trying to do (and also imprecise in their instructions).
Download 8.0.0.4-WS-MQ-Install-Java-All file
Run it like java -jar 8.0.0.4-WS-MQ-Install-Java-All.jar and accept the license agreement
Add all .jars from wmq/JavaSE/ folder to JMeter Classpath
Restart JMeter to pick the .jars up
Add JSR223 Sampler to your Test Plan and put the following code into "Script" area:
import com.ibm.msg.client.jms.JmsFactoryFactory
import com.ibm.msg.client.wmq.WMQConstants
import javax.jms.Session
// 1
def hostName = "127.0.0.1"
def hostPort = 1414
def channelName = "DEV.APP.SVRCONN"
def queueManagerName = "QM1"
def queueName = "DEV.QUEUE.1"
// 2
def ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER)
def cf = ff.createConnectionFactory()
// 3
cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, hostName)
cf.setIntProperty(WMQConstants.WMQ_PORT, hostPort)
cf.setStringProperty(WMQConstants.WMQ_CHANNEL, channelName)
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT)
cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, queueManagerName)
// 4
def conn = cf.createConnection("app", "")
def sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE)
// 5
def destination = sess.createQueue(queueName)
conn.start()
See IBM MQ testing with JMeter - Learn How article for more information if needed.

Qpid receiver on Azure EventHub

I have already working application based on Azure EventHub. Now I need write java receiver that connects to the existing infrastructure.
Existing configuration:
Event Hub > SomeName > Consumer Group > SomeGroupName
In the administrative console I cannot see any QUEUE or TOPIC definitions. Analyzing working c# code I can see that hub-name + group-name is enough to connect.
I have reconstructed url that allows me to connect over java (and connection works so far).
amqps://SomeName.servicebus.windows.net
So my questions:
1) When instead of queue /topic I specify group-name then I get exception The messaging entity 'sb://SomeName.servicebus.windows.net/SomeGroupName' could not be found. What is the model used there instead of queue/topic?
2) How to work with such infrastructure from Apache-qpid?
Are you using the Event Hub created in the old portal or one created using the new portal?
EventHub is not a Message Bus, so there are no Queues or Topics, that is correct.
The consumer group is not a part of the address. The address is build using the namespace and the name of the eventhub in that namespace.
So the address becomes:
sb://SomeNameSpaceName.servicebus.windows.net/SomeEventHubName
Can you post the c# code you've analyzed? Since you have an already working application maybe we can workout the differences that prevents it from working now.
The greatest hint for resolve the question gave me following link: http://theitjourney.blogspot.com/2015/12/sendreceive-messages-using-amqp-in-java.html
So No queue neither topic in this model. You need to connect to specific provider and specify correct EventHub as following:
application.properties:
connectionfactory.SBCF=amqps://<PolicyName>:<PolicyKey>#<DomainName>.servicebus.windows.net
queue.EventHub=<EventHubName>/ConsumerGroups/$Default/Partitions/0
Where:
After that following code allowed me to create MessageConsumer:
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.qpid.amqp_1_0.jms.jndi.PropertiesFileInitialContextFactory");
env.put(Context.PROVIDER_URL,
getClass().getResource("/application.properties").toString());
Context context = null;
context = new InitialContext(env);
// Look up ConnectionFactory
ConnectionFactory cf = (ConnectionFactory) context.lookup("SBCF");
Destination queue = (Destination) context.lookup("EventHub");
// Create Connection
Connection connection = cf.createConnection();
// Create receiver-side Session, MessageConsumer
Session receiveSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer receiver = receiveSession.createConsumer(queue);

How do you use consistent hashing with the java elasticache libs?

Im trying to use elasticache as a memcache service with AWS's elasticache client library for java.
The following code works for connecting to the cluster:
_client = new MemcachedClient(_serverList);
But any attempt I've made to use consistent hashing results in memcache client failing to initialize:
_client = new MemcachedClient(new KetamaConnectionFactory(), _serverList);
or
ConnectionFactoryBuilder connectionFactoryBuilder = new ConnectionFactoryBuilder();
connectionFactoryBuilder.setLocatorType(Locator.CONSISTENT);
connectionFactoryBuilder.setHashAlg(DefaultHashAlgorithm.KETAMA_HASH);
connectionFactoryBuilder.setClientMode(ClientMode.Dynamic);
ConnectionFactory connectionFactory = connectionFactoryBuilder.build();
_client = new MemcachedClient(connectionFactory, _serverList);
Any attempt I've made to use anything but a vanilla MemcacheClient results in errors such as :
2015-04-07 07:00:32.914 WARN net.spy.memcached.ConfigurationPoller: The configuration is null in the server localhost
2015-04-07 07:00:32.914 WARN net.spy.memcached.ConfigurationPoller: Number of consecutive poller errors is 7. Number of minutes since the last successful polling is 0
Also, I've verified with telnet, spymecached libs, and the vanilla MemcacheClient constructor, that the security groups are permissive.
When using the AWS Client Library KetamaConnectionFactory defaults to the "dynamic" client mode which tries to poll the list of available memcached nodes from the configuration endpoint. For this to work your _serverList should only contain the configuration endpoint.
Your error message indicates the host was a "plain" memcached node which doesn't understand the ElastiCache extensions. If this is what you intend to do (specify the nodes yourself rather than use the autodiscovery feature) then you need to use the multiple-arg KetamaConnectionFactory constructor and pass in ClientMode.Static as the first argument.
You will need to use the AddrUtil.getAddresses() method.
_client = new MemcachedClient(new KetamaConnectionFactory(), AddrUtil.getAddresses("configEndpoint:port"));
or
ConnectionFactoryBuilder connectionFactoryBuilder = new ConnectionFactoryBuilder(new KetamaConnectionFactory());
// set any other properties you want on the builder
ConnectionFactory connectionFactory = connectionFactoryBuilder.build();
_client = new MemcachedClient(connectionFactory, AddrUtil.getAddresses("configEndpoint:port"));

DetailedJMSSecurityException while trying to access queue in IBM MQ

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.

Issues with connecting to ibm mq 7.5 using java

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

Categories