Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apache Camel MQXAQueueConnectionFactory

So well, I am trying to get a MQXAQueueConnectionFactory to work, I have created a extended class from the JmsComponent to handle username and password when sending data to the queue. It does get/put messages on the queue, but in my case I've created a router to test the XA such as

 from("wmq:queue:incomingQueue")
     .process(new Processor(){
     ... Thread.sleep(20000)
     })
     .to("wmq:queue:outgoingQueue")

while being in sleep, I shut down the queuemanager. However when trying to get uncommited messages from the queue DISPLAY QSTATUS('qChainQueue') i get CURDEPTH(0), while it should be 1 as I understand the XA part.

  • Am I doing this totally wrong?
  • How can it be tested?

HelpClass to handle WMQ:

public class WMQComponent extends JmsComponent {
    private final String username;
    private final String password;

    public WMQComponent(String hostname, int port, String username, String password,
                        String queueManager, String channel) throws JMSException {
        super();
        this.username = username;
        this.password = password;

        MQXAQueueConnectionFactory connectionFactory = new MQXAQueueConnectionFactory();
        connectionFactory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
        connectionFactory.setFailIfQuiesce(1);

        connectionFactory.setHostName(hostname);
        connectionFactory.setPort(port);
        connectionFactory.setQueueManager(queueManager);
        connectionFactory.setChannel(channel);

        setConnectionFactory(connectionFactory);
    }

    @Override
    public Endpoint createEndpoint(String uri) throws Exception {
        if (uri.contains("username") || uri.contains("password")) {
            throw new IllegalStateException("Username and password is set by the component");
        }
        if (uri.contains("?")) {
            return super.createEndpoint(uri + "&username=" + username + "&password=" + password);
        } else {
            return super.createEndpoint(uri + "?username=" + username + "&password=" + password);
        }
    }

}

With the following errors:

2015-03-25 14:01:12,077 [ #2 - Multicast] INFO  dest_chain_ldap                - org.springframework.jms.IllegalStateException: JMSWMQ0018: Failed to connect to queue manager 'QMBATCHESB' with connection mode 'Client' and host name 'hostname.com'.; nested exception is com.ibm.msg.client.jms.DetailedIllegalStateException: JMSWMQ0018: Failed to connect to queue manager 'QMBATCHESB' with connection mode 'Client' and host name 'hostname.com'. Check the queue manager is started and if running in client mode, check there is a listener running. Please see the linked exception for more information.; nested exception is com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2059' ('MQRC_Q_MGR_NOT_AVAILABLE').
    at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:279)
    at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:168)
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:469)
    at org.apache.camel.component.jms.JmsConfiguration$CamelJmsTemplate.send(JmsConfiguration.java:228)
    at org.apache.camel.component.jms.JmsProducer.doSend(JmsProducer.java:431)
    at org.apache.camel.component.jms.JmsProducer.processInOnly(JmsProducer.java:385)
    at org.apache.camel.component.jms.JmsProducer.process(JmsProducer.java:153)
    at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:120)
    at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:72)
    at org.apache.camel.processor.interceptor.TraceInterceptor.process(TraceInterceptor.java:163)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:416)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:118)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:80)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
    at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:51)
    at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:120)
    at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:72)
    at org.apache.camel.processor.interceptor.TraceInterceptor.process(TraceInterceptor.java:163)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:416)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
    at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:105)
    at org.apache.camel.processor.MulticastProcessor.doProcessParallel(MulticastProcessor.java:732)
    at org.apache.camel.processor.MulticastProcessor.access$200(MulticastProcessor.java:82)
    at org.apache.camel.processor.MulticastProcessor$1.call(MulticastProcessor.java:303)
    at org.apache.camel.processor.MulticastProcessor$1.call(MulticastProcessor.java:288)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
Caused by: com.ibm.msg.client.jms.DetailedIllegalStateException: JMSWMQ0018: Failed to connect to queue manager 'QMBATCHESB' with connection mode 'Client' and host name 'hostname.com'. Check the queue manager is started and if running in client mode, check there is a listener running. Please see the linked exception for more information.
    at com.ibm.msg.client.wmq.common.internal.Reason.reasonToException(Reason.java:496)
    at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:236)
    at com.ibm.msg.client.wmq.internal.WMQConnection.<init>(WMQConnection.java:430)
    at com.ibm.msg.client.wmq.internal.WMQXAConnection.<init>(WMQXAConnection.java:70)
    at com.ibm.msg.client.wmq.factories.WMQXAConnectionFactory.createV7ProviderConnection(WMQXAConnectionFactory.java:190)
    at com.ibm.msg.client.wmq.factories.WMQConnectionFactory.createProviderConnection(WMQConnectionFactory.java:6210)
    at com.ibm.msg.client.jms.admin.JmsConnectionFactoryImpl.createConnection(JmsConnectionFactoryImpl.java:278)
    at com.ibm.mq.jms.MQConnectionFactory.createCommonConnection(MQConnectionFactory.java:6155)
    at com.ibm.mq.jms.MQQueueConnectionFactory.createQueueConnection(MQQueueConnectionFactory.java:144)
    at com.ibm.mq.jms.MQQueueConnectionFactory.createConnection(MQQueueConnectionFactory.java:223)
    at org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter.doCreateConnection(UserCredentialsConnectionFactoryAdapter.java:175)
    at org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter.createConnection(UserCredentialsConnectionFactoryAdapter.java:150)
    at org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.java:184)
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:456)
    ... 29 more
Caused by: com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2059' ('MQRC_Q_MGR_NOT_AVAILABLE').
    at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:223)
    ... 41 more
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2059;AMQ9204: Connection to host 'hostname.com(1514)' rejected. [1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2059;AMQ9213: A communications error for  occurred. [1=java.net.ConnectException[Connection refused: connect],3=hostname.com]],3=hostname.com(1514),5=RemoteTCPConnection.connnectUsingLocalAddress]
    at com.ibm.mq.jmqi.remote.internal.RemoteFAP.jmqiConnect(RemoteFAP.java:1831)
    at com.ibm.msg.client.wmq.internal.WMQConnection.<init>(WMQConnection.java:345)
    ... 40 more
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2059;AMQ9213: A communications error for  occurred. [1=java.net.ConnectException[Connection refused: connect],3=hostname.com]
    at com.ibm.mq.jmqi.remote.internal.RemoteTCPConnection.connnectUsingLocalAddress(RemoteTCPConnection.java:612)
    at com.ibm.mq.jmqi.remote.internal.RemoteTCPConnection.protocolConnect(RemoteTCPConnection.java:940)
    at com.ibm.mq.jmqi.remote.internal.system.RemoteConnection.connect(RemoteConnection.java:1097)
    at com.ibm.mq.jmqi.remote.internal.system.RemoteConnectionPool.getConnection(RemoteConnectionPool.java:348)
    at com.ibm.mq.jmqi.remote.internal.RemoteFAP.jmqiConnect(RemoteFAP.java:1503)
    ... 41 more
Caused by: java.net.ConnectException: Connection refused: connect
    at java.net.DualStackPlainSocketImpl.connect0(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:69)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:157)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)
    at java.net.Socket.connect(Socket.java:579)
    at java.net.Socket.connect(Socket.java:528)
    at com.ibm.mq.jmqi.remote.internal.RemoteTCPConnection$2.run(RemoteTCPConnection.java:597)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.ibm.mq.jmqi.remote.internal.RemoteTCPConnection.connnectUsingLocalAddress(RemoteTCPConnection.java:588)
    ... 45 more
like image 330
J2B Avatar asked Mar 25 '15 13:03

J2B


People also ask

Is Apache Camel outdated?

Many open source projects and closed source technologies did not withstand the tests of time and have disappeared from the middleware stacks for good. After a decade, however, Apache Camel is still here and becoming even stronger for the next decade of integration.

What is Apache Camel used for?

Apache Camel ™ is a versatile open-source integration framework based on known Enterprise Integration Patterns. Camel empowers you to define routing and mediation rules in a variety of domain-specific languages (DSL, such as Java, XML, Groovy, Kotlin, and YAML).

Is Apache Camel good?

Apache Camel is a great choice when you're working with data that needs to be shared between systems. This happens when you have data stored in different applications. For example, personnel files might be stored in an HR system, but need need to be shared with Finance to be able to process the monthly payroll.

What is Seda in Apache Camel?

The SEDA component provides asynchronous SEDA behavior, so that messages are exchanged on a BlockingQueue and consumers are invoked in a separate thread from the producer. Note that queues are only visible within a single CamelContext.


2 Answers

The reason code 2059 and various errors stating that the connection was refused suggest either a mechanical issue (i.e. Listener not running) or an auths issue.

If I were attempting to debug this, the first thing I'd do is to enable authorization events, channel events, and any others you would normally enable. If you use MQ Explorer, also install the MS0P Plugin which will allow you to view the event messages in human-readable text.

Next, I would use the MQ sample programs to test. Since I always install the full client rather than grabbing the jar files, I have amqsputc available. However, the Java classes have IVT (initial verification test) programs. These ensure that the listener is running, the channel is configured and available, etc. As of v7.1 this also ensures that the CHLAUTH rules are set to allow the access. As of v8.0, or if you had the Capitalware exit installed, this also lets us test the user ID and password authentication.

The queue manager's error log and the event messages should provide good diagnostics, assuming the connection request makes it to MQ. Be sure to look both in the QMgr-specific error logs and the installation-global error logs.

Once I had confirmed that basic connectivity is in place, I'd reconcile my client-side configuration parameters for host, port, channel and if it is specified [shudder!] the QMgr name. Assuming these are correct and having proven basic connectivity works, it is now possible to test the app with some confidence.

The same method applies. First make sure the app's connection request makes it to the QMgr. If it does and is refused, the event messages and error logs will note this and why. If there is no indication of a failure in these places, the app isn't getting to the QMgr. The 2059 can indicate that the socket was refused, that the listener is up but the QMgr is not, that the channel instances have maxed out, or that after provisionally starting the channel it was closed by the QMgr, often due to a CHLAUTH rule. In any case, the event messages and error logs will have a detailed explanation as to why.

like image 107
T.Rob Avatar answered Sep 26 '22 22:09

T.Rob


So I had done this a bit wrong, it was not enough to use the MQXAConnectionFactory but I had to create the JmsComponent as transacted.

Have tried to stop the queue manager while running the application and stop the application while handling a message and it seems to do the rollback as expected.

Ended up with

public static JmsComponent mqXAComponentTransacted(String hostname, int port, String username, String password,
                           String queueManager, String channel) throws JMSException {
    MQXAQueueConnectionFactory connectionFactory = new MQXAQueueConnectionFactory();
    connectionFactory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
    connectionFactory.setFailIfQuiesce(1);
    connectionFactory.setHostName(hostname);
    connectionFactory.setPort(port);
    connectionFactory.setQueueManager(queueManager);
    connectionFactory.setChannel(channel);

    UserCredentialsConnectionFactoryAdapter connectionFactoryAdapter=new UserCredentialsConnectionFactoryAdapter();
    connectionFactoryAdapter.setTargetConnectionFactory(connectionFactory);
    connectionFactoryAdapter.setUsername(username);
    connectionFactoryAdapter.setPassword(password);

    return JmsComponent.jmsComponentTransacted(connectionFactoryAdapter);
}

Also using the UserCredentialsConnectionFactoryAdapter, I didn't want to use Spring components but since the Jms package is already dependent of it, it was easier to use it than my previous solution to handle credentials.

like image 35
J2B Avatar answered Sep 26 '22 22:09

J2B