In my last blog Integrated IBM MQ support in IBM z/OS Connect Enterprise Edition I walked through creating a new IBM MQ service to in IBM z/OS Connect Enterprise Edition. What I didn’t show was what would happen when if I made a mistake. In this blog I am going to show what happens when things do not work as expected. This will be covered by the following 4 questions:

  1. What if the queue manager/queue doesn’t exist?
  2. The service is returning a data transformation error, how do I pin point the error?
  3. How do I check the SAR is using the right copybooks?
  4. I have a C back-end application what do I do?

In this article I have used the Linux utility json_xs to format the JSON that is returned.

What if the queue manager/queue doesn’t exist?

As the MQ service provider is written as a JMS application any errors that are found are reported as exceptions. These will be caught and sent back to the REST client as JSON. The example below is the response that will be seen when the queue manager isn’t available:

{
   "explanation" : "An unexpected JMSException occurred while processing a request.",
   "exceptionData" : {
      "exceptions" : [
         {
            "stackTrace" : [
               "com.ibm.msg.client.jms.DetailedJMSException: MQJCA1011: Failed to allocate a JMS connection.",
               "at com.ibm.mq.connector.services.JCAExceptionBuilder.buildException(JCAExceptionBuilder.java:184)",
               "at com.ibm.mq.connector.services.JCAExceptionBuilder.buildException(JCAExceptionBuilder.java:135)",
               "at com.ibm.mq.connector.outbound.ConnectionFactoryImpl.createManagedJMSConnection(ConnectionFactoryImpl.java:402)",
...
            ]
         },
         {
            "stackTrace" : [
               "com.ibm.msg.client.jms.DetailedIllegalStateException: JMSWMQ0018: Failed to connect to queue manager 'MQ25' with connection mode 'Client' and host name 'localhost(1525)'.",
               "at com.ibm.msg.client.wmq.common.internal.Reason.reasonToException(Reason.java:489)",
               "at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:215)",
...
            ]
         },
         {
            "stackTrace" : [
               "com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2538' ('MQRC_HOST_NOT_AVAILABLE').",
               "at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:203)",
               "at com.ibm.msg.client.wmq.internal.WMQConnection.(WMQConnection.java:424)",
               "at com.ibm.msg.client.wmq.internal.WMQXAConnection.(WMQXAConnection.java:67)",
               "at com.ibm.msg.client.wmq.factories.WMQXAConnectionFactory.createV7ProviderConnection(WMQXAConnectionFactory.java:187)",
               "at com.ibm.msg.client.wmq.factories.WMQConnectionFactory.createProviderConnection(WMQConnectionFactory.java:7815)",
               "at com.ibm.msg.client.wmq.factories.WMQXAConnectionFactory.createProviderXAConnection(WMQXAConnectionFactory.java:98)",
               "at com.ibm.msg.client.jms.admin.JmsConnectionFactoryImpl.createXAConnectionInternal(JmsConnectionFactoryImpl.java:354)",
               "at com.ibm.mq.jms.MQXAConnectionFactory.createXAConnection(MQXAConnectionFactory.java:131)",
               "at com.ibm.mq.connector.ConnectionBuilder.createConnection(ConnectionBuilder.java:134)",
               "at com.ibm.mq.connector.outbound.ManagedConnectionFactoryImpl.createConnection(ManagedConnectionFactoryImpl.java:571)",
               "at com.ibm.mq.connector.outbound.ManagedConnectionImpl.(ManagedConnectionImpl.java:174)",
               "at com.ibm.mq.connector.outbound.ManagedConnectionFactoryImpl.createManagedConnection(ManagedConnectionFactoryImpl.java:236)",
               "at com.ibm.ejs.j2c.FreePool.createManagedConnectionWithMCWrapper(FreePool.java:1361)",
               "at com.ibm.ejs.j2c.FreePool.createOrWaitForConnection(FreePool.java:1231)",
               "at com.ibm.ejs.j2c.PoolManager.reserve(PoolManager.java:1460)",
               "at com.ibm.ejs.j2c.ConnectionManager.allocateMCWrapper(ConnectionManager.java:575)",
               "at com.ibm.ejs.j2c.ConnectionManager.allocateConnection(ConnectionManager.java:311)",
               "at com.ibm.mq.connector.outbound.ConnectionFactoryImpl.createManagedJMSConnection(ConnectionFactoryImpl.java:309)",
               "at com.ibm.mq.connector.outbound.ConnectionFactoryImpl.createConnectionInternal(ConnectionFactoryImpl.java:252)",
               "at com.ibm.mq.connector.outbound.ConnectionFactoryImpl.createConnection(ConnectionFactoryImpl.java:225)",
               "at com.ibm.mq.connector.outbound.ConnectionFactoryImpl.createConnection(ConnectionFactoryImpl.java:201)",
               "at com.ibm.zosconnect.service.mq.MQServiceInvocation.createConnection(MQServiceInvocation.java:842)",
               "at com.ibm.zosconnect.service.mq.TwoWayMQServiceInvocation.createJMSObjectsForRequest(TwoWayMQServiceInvocation.java:277)",
               "at com.ibm.zosconnect.service.mq.TwoWayMQServiceInvocation.sendMessage(TwoWayMQServiceInvocation.java:121)",
               "at com.ibm.zosconnect.service.mq.TwoWayMQServiceInvocation.invoke(TwoWayMQServiceInvocation.java:107)",
               "at com.ibm.zosconnect.service.mq.MQService.invoke(MQService.java:550)",
...
            ]
         },
         {
            "stackTrace" : [
               "com.ibm.mq.jmqi.JmqiException: CC=2;RC=2538;AMQ9204: Connection to host 'localhost(1525)' rejected. [1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2538;AMQ9213: A communications error for 'TCP' occurred. [1=java.net.ConnectException[EDC8128I Connection refused. (Connection refused)],3=connnectUsingLocalAddress,4=TCP,5=Socket.connect]],3=localhost(1525),5=RemoteTCPConnection.connnectUsingLocalAddress]",
               "at com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiConnect(RemoteFAP.java:2302)",
               "at com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiConnect(RemoteFAP.java:1273)",
...
            ]
         },
         {
            "stackTrace" : [
               "com.ibm.mq.jmqi.JmqiException: CC=2;RC=2538;AMQ9213: A communications error for 'TCP' occurred. [1=java.net.ConnectException[EDC8128I Connection refused. (Connection refused)],3=connnectUsingLocalAddress,4=TCP,5=Socket.connect]",
               "at com.ibm.mq.jmqi.remote.impl.RemoteTCPConnection.connnectUsingLocalAddress(RemoteTCPConnection.java:852)",
               "at com.ibm.mq.jmqi.remote.impl.RemoteTCPConnection.protocolConnect(RemoteTCPConnection.java:1294)",
               "at com.ibm.mq.jmqi.remote.impl.RemoteConnection.connect(RemoteConnection.java:1011)",
               "at com.ibm.mq.jmqi.remote.impl.RemoteConnectionSpecification.getSessionFromNewConnection(RemoteConnectionSpecification.java:416)",
               "at com.ibm.mq.jmqi.remote.impl.RemoteConnectionSpecification.getSession(RemoteConnectionSpecification.java:312)",
...
            ]
         },
         {
            "stackTrace" : [
               "java.net.ConnectException: EDC8128I Connection refused. (Connection refused)",
            ]
         }
      ]
   },
   "action" : "Use the information accompanying this message to resolve the problem, then resubmit the request.",
   "message" : "BAQM0006E: An unexpected JMSException occurred while processing a request for service 'addNumbersService'."
}

Although the response is large, the 3rd exception stack trace shows an MQRC. In this case its MQRC_HOST_NOT_AVAILABLE but other errors will be shown in a similar way. For those of us who know MQ seeing a MQRC gives a warm feeling.

The service is returning a data transformation error, how do I pin point the error?

When developing a service you are likely to experience data transformation errors (I did). So I thought that I would show what you are likely to see and how you can use it to help you to solve the issue.

curl -i -k -X POST https://winmvs41.hursley.ibm.com:9444/zosConnect/services/calculateService?action=invoke -H Content-Type:application/json -u "fred:fredpwd" -d '{"TESTOperation" : { "instruc" : {"number1" : "1", "number3" : "2"}}}'

I am going to use the service that we created in my previous blog Integrated IBM MQ support in IBM z/OS Connect Enterprise Edition but I have specified ‘number3’ instead of ‘number2’. When I try to use the service I get an error response like the one below:

{
   "explanation" : "The structure of the request data should conform to the data transformation schema.",
   "exceptionData" : {
      "exceptions" : [
         {
            "stackTrace" : [
               "com.ibm.zosconnect.spi.DataXformException: DFHPI1007 JSON to data transformation failed because of incorrect input (UNDEFINED_ELEMENT number3).",
               "at com.ibm.zosconnect.internal.xform.DataXformImpl.jsonToBytes(DataXformImpl.java:1000)",
               "at com.ibm.zosconnect.internal.xform.DataXformImpl.getBytes(DataXformImpl.java:447)",
               "at com.ibm.zosconnect.internal.RequestDataHandler$RequestDataImpl.getBytes(RequestDataHandler.java:323)",
               "at com.ibm.zosconnect.service.mq.MQServiceInvocationData.getRequestBytes(MQServiceInvocationData.java:153)",
               "at com.ibm.zosconnect.service.mq.MQServiceInvocation.prepareMessageForSend(MQServiceInvocation.java:718)",
               "at com.ibm.zosconnect.service.mq.TwoWayMQServiceInvocation.sendMessage(TwoWayMQServiceInvocation.java:124)",
               "at com.ibm.zosconnect.service.mq.TwoWayMQServiceInvocation.invoke(TwoWayMQServiceInvocation.java:107)",
               "at com.ibm.zosconnect.service.mq.MQService.invoke(MQService.java:550)",
               "at com.ibm.zosconnect.internal.ZosConnectServiceImpl.invoke(ZosConnectServiceImpl.java:1064)",
               "at com.ibm.zosconnect.internal.ServiceManagerImpl.invoke(ServiceManagerImpl.java:1330)",
               "at com.ibm.zosconnect.internal.web.ServiceProxyServlet$21.run(ServiceProxyServlet.java:2045)",
               "at com.ibm.ws.webcontainer.async.ServiceWrapper.wrapAndRun(ServiceWrapper.java:236)",
               "at com.ibm.ws.webcontainer.async.ContextWrapper.run(ContextWrapper.java:28)",
               "at com.ibm.ws.webcontainer.async.WrapperRunnableImpl.run(WrapperRunnableImpl.java:89)",
               "at com.ibm.ws.threading.internal.ExecutorServiceImpl$RunnableWrapper.run(ExecutorServiceImpl.java:232)",
               "at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1160)",
               "at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)",
               "at java.lang.Thread.run(Thread.java:812)"
            ]
         }
      ]
   },
   "action" : "Ensure the request data conforms to the data transformation schema. Contact the administrator of the service if the schema was not provided.",
   "message" : "BAQM0002E: The request data for service 'addNumbersService' is incorrect for the configured data transformation."
}

As you may have noticed the first line of the stackTrace has a DFH message prefix. This message has the name of the data field which is likely to be wrong. Different errors in the input JSON will produce different response messages but the response should guide you to where to start looking. Some points to be aware of:

  • If a field in the structure is a number then the number in the JSON should not be surrounded by quotes.
  • Ensure that the structure of the JSON matches the structure of the data fields with the required ‘[‘, ‘]’, ‘{‘, and ‘}‘ brackets. See the How do I check the SAR is using the right copybooks question for more information.
  • Ensure that the data area(s) that you are giving z/OS Connect either on the request or response flow are what you are expecting. It is easy to misconfigure the SAR properties so you think the request and response use different copybooks but the same copybook is used for both.

How do I check the SAR is using the right copybooks?

A SAR is like a zip or jar so can be open by applications that can open them. If you look in the ‘schemas’ directory you should see 2 JSON files. An example is shown below.

These files are the JSON schemas that are generated from the copy books that are read in. If I open one I will see the structure of the JSON and what data is permitted. An example is shown below:

By using this information we can generate the input JSON with the correct attributes and structure.

I have a C back-end application what do I do?

The MQ support in the build toolkit only supports copybooks written in COBOL or PL1 due to underling restrictions. If you want to use back end application written in C, don’t fear. We can still use COBOL or PL1 to define the structure for the service definition. The key is to use the correct matching data types so when the service puts the message on to the queue the data is in the locations which the application expects.

Join The Discussion

Your email address will not be published.