JAVA to EBCIDIC Conversion is not happening

纵饮孤独 提交于 2020-06-17 13:59:23

问题


I am trying to get data from one application and send that to another(mainframe) after processing the data.

Lets assume I am getting data as "This is from another application", processed the same and processing status as "This data is processed". Final message should be combination of both using encoding(Cp1047) to mainframe application to read the same as

0024This is from another application001AThis data is processed


decimal value of 0024 is 36 (message length + 4 which is hexa value length)
decimal value of 001A is 26 (processed message length + 4)

My application runs on Java8 and uses websphere MQ. I need to send data to application which receives data from Mainframe MQ. Remote queue in WebSphere MQ puts messge to Local Queue of Mainframe MQ. My code as below to convert data and encode using Cp1047,

String incomingData = "This is from another application";
String processingData = "This data is processed" 
public String outGoingData(String incomingData, String processingData) {  
  StringBuilder strBuilder = new StringBuilder();
  return stringbuilder.append(new String(convertToEbcidie(incomingData, "Cp1047")))
  .append(incomingData)
  .append(new String(convertToEbcidie(processingData, "Cp1047")))
  .append(processing data).toString(); //playing this string to queue
}
private byte[] convertToEbcidic(String s) {
  String hexStr = StringUtils.leftPad(s.length+4, 8, "0");
  byte[] byteAry = new byte[hexStr.length()/2];
  for (int i = 0; i < hexStr.length(); i+=2) {
    byteAry[i/2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                   + Character.digit(s.charAt(i+1), 16)); 
  }  return byteAry;
}

Receiver application(mainframe) decide which is original message and processing status based hexavalue which is 4 characters. They are able to read most of the messages but not all. for ex, hexa value of length 805 is 325, but in mainframe mq entry is as 315. They are not able to process since the length mismatches.

ANOTHER SAMPLE DATA :- OO25THIS IS ORIGINAL DATA FROM SOURCE001APROCESSED SUCCESSFULLY


0025 is hexval of org msg length(33) + 4 and 001A is hexval of processed msg length (22) + 4. Here 4 is the length of hexa decimal value.
Am I missing any logic to convert to ebcidic?


回答1:


There is so much wrong with the code you posted, I don't know where to begin.

First off, StackOverflow rules/policy is that you are supposed to copy & paste your working code from your editor or IDE to StackOverflow. Clearly, you did not do that but rather just created new code in the StackOverflow edit window - which is wrong!!!

return stringbuilder.append(new String(convertToEbcidie(incomingData, "Cp1047")))
  .append(incomingData)
  .append(new String(convertToEbcidie(processingData, "Cp1047")))
  .append(processing data).toString();

(1) The convertToEbcidic method takes ONE parameter and not 2. You have your bracketing wrong.

(2) The method name is convertToEbcidic and not convertToEbcidie (last letter is 'c' not 'e')

private byte[] convertToEbcidic(String s) {
  String hexStr = StringUtils.leftPad(s.length+4, 8, "0");
  byte[] byteAry = new byte[hexStr.length()/2];
  for (int i = 0; i < hexStr.length(); i+=2) {
    byteAry[i/2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                   + Character.digit(s.charAt(i+1), 16)); 
  }  return byteAry;
}

(3) I have no clue what you are trying to do but clearly it is not doing anything you think it is. Did you step through the code with a debugger?

(3A) The length for s variable is a method not a field. It should be "s.length()" and not "s.length".

(3B) StringUtils.leftPad method's first parameter must be a String and not an int.

(3C) hexStr will be "00000036" (32 + 4). hexStr has a length of 8.

(3D) byteAry will have a size of 4!!! How are you suppose to fit 36 characters into 4 bytes? i.e. 4 + 26 characters "This is from another application".

(3E) What is your loop doing?? It runs 4 times and I have absolutely no idea what you were thinking.

Ok. Now to your problem.

ANOTHER SAMPLE DATA :- OO25THIS IS ORIGINAL DATA FROM SOURCE001APROCESSED SUCCESSFULLY

Ok. So based on that sample, it appears to me that the layout is as following:

{string representation of length of "character data 1" in hex}{character data 1}{string representation of length of "character data 2" in hex}{character data 2}

Since, the entire message payload will be string then it is far, far better to put the string as a message in the local codepage (ASCII), mark the MQMD format as string and let MQ do the conversion. The conversion will be done when the mainframe application issues an "MQGET with Convert" call.

Here is the proper code to your problem:

String incomingData = "This is from another application";
String processingData = "This data is processed";
StringBuilder sb = new StringBuilder();
MQQueueManager qMgr = null;
MQQueue outQ = null;

String inHexLen = Integer.toHexString(incomingData.length()+4).toUpperCase();
inHexLen = StringUtils.leftPad(inHexLen, 4, '0');
sb.append(inHexLen);
sb.append(incomingData);

String outHexLen = Integer.toHexString(processingData.length()+4).toUpperCase();
outHexLen = StringUtils.leftPad(outHexLen, 4, '0');
sb.append(outHexLen);
sb.append(processingData);

System.out.println("sb="+sb.toString());

try
{
   qMgr = new MQQueueManager("MQA1");

   outQ = qMgr.accessQueue("TEST.Q1",
                           CMQC.MQOO_OUTPUT + CMQC.MQOO_FAIL_IF_QUIESCING);

   MQMessage sendmsg = new MQMessage();
   sendmsg.format = CMQC.MQFMT_STRING;
   sendmsg.writeString(sb.toString());
   outQ.put(sendmsg, new MQPutMessageOptions());
}
catch (MQException e)
{
   e.printStackTrace();
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   try
   {
      if (outQ != null)
         outQ.close();
   }
   catch (MQException e)
   {
      e.printStackTrace();
   }
   try
   {
      if (qMgr != null)
         qMgr.disconnect();
   }
   catch (MQException e)
   {
      e.printStackTrace();
   }
}



回答2:


It seems like you try to mix binary- and text-data in your message and the way you want to do it is as follows:

  • You take the binary fields and do an EBCDIC->client-codepage conversion on the client side
  • Then you pass it to MQ which then does a client-codepage->EBCDIC conversion
  • You hope you'll be back where you started

This could work but in most cases it won't because it requires that:

  • your character-transformation and MQ's character-transformation use identical conversion-tables
  • those conversion-tables are bijective, i.e. they allow for lossless roundtrip-conversion

Especially the last point is generally not true for non-printable (or even non-mapped) byte-values.

So either transfer your data as binary without conversion or as text with conversion, but any attempt to mix both is bound to fail.




回答3:


In the data you are sending to zOS, are some characters that are ASCII and some bytes that contain a length

If you put that complete string - of combined text characters through a code conversion, then that is what happens to every byte in the complete string - whatever does the code conversion will try to convert every byte from it's ASCII value to an equivalent "EBCDIC" value.

Thus at the end of the conversion, the text characters are ok, as they are normal printable characters, but the bytes containing the length, will have been converted to some EBCDIC char and are no longer usable to do length calculations.

Since it seems your app on zOS is GETting the message from MQ, you need to make sure you GET the message from MQ on zOS so that MQ does NO conversion for you.

Then rather then converting the whole message to EBCDIC in one operation, you need to parse the message.

Get the first two bytes of the message into a variable ( with no conversion ) which have the length of the first text, google how to write Java code to convert that to a java int, then use that value to get those N bytes out of the MQ string, and then do a conversion to EBCDIC on those bytes,

then get the two bytes from the MQ message after the end of that 1st string, and repeat above process.



来源:https://stackoverflow.com/questions/61667002/java-to-ebcidic-conversion-is-not-happening

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!