I am new on attempting to unpack Jpos message, I try to follow the only answer from this old question JPOS unpacking running example
However, I receive this error
Error handling message -> org.jpos.iso.ISOException: field packager '5' is null unpacking field=5, consumed=50
and this is my iso message in hex form
49534F3031353030303037303032313046323341383030314145393038303130...
(notes: I purposely cut the message short since the rest has sensitive info)
I am using a custom packager as this following
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE isopackager SYSTEM "genericpackager.dtd">
<!-- ISO 8583:1987 (ASCII) field descriptions for GenericPackager -->
<!-- Bitmap is BINARY in this case -->
<isopackager headerLength="12">
<isofield
id="0"
length="4"
name="MESSAGE TYPE INDICATOR"
class="org.jpos.iso.IFA_NUMERIC"/>
<isofield
id="1"
length="16"
name="BIT MAP"
class="org.jpos.iso.IFA_BITMAP"/>
<isofield
id="2"
length="19"
name="PAN - PRIMARY ACCOUNT NUMBER"
class="org.jpos.iso.IFA_LLNUM"/>
<isofield
id="3"
length="6"
name="PROCESSING CODE"
class="org.jpos.iso.IFA_NUMERIC"/>
<isofield
id="4"
length="12"
name="AMOUNT, TRANSACTION"
class="org.jpos.iso.IFA_NUMERIC"/>
<isofield
id="7"
length="10"
name="TRANSMISSION DATE AND TIME"
class="org.jpos.iso.IFA_NUMERIC"/>
<isofield
id="11"
length="6"
name="SYSTEM TRACE AUDIT NUMBER"
class="org.jpos.iso.IFA_NUMERIC"/>
<isofield
id="12"
length="6"
name="TIME, LOCAL TRANSACTION"
class="org.jpos.iso.IFA_NUMERIC"/>
<isofield
id="13"
length="4"
name="DATE, LOCAL TRANSACTION"
class="org.jpos.iso.IFA_NUMERIC"/>
<isofield
id="15"
length="4"
name="DATE, SETTLEMENT"
class="org.jpos.iso.IFA_NUMERIC"/>
<isofield
id="17"
length="4"
name="DATE, CAPTURE"
class="org.jpos.iso.IFA_NUMERIC"/>
<isofield
id="32"
length="11"
name="ACQUIRING INSTITUTION IDENT CODE"
class="org.jpos.iso.IFA_LLNUM"/>
<isofield
id="33"
length="11"
name="FORWARDING INSTITUTION IDENT CODE"
class="org.jpos.iso.IFA_LLNUM"/>
<isofield
id="35"
length="37"
name="TRACK 2 DATA"
class="org.jpos.iso.IFA_LLNUM"/>
<isofield
id="37"
length="12"
name="RETRIEVAL REFERENCE NUMBER"
class="org.jpos.iso.IF_CHAR"/>
<isofield
id="38"
length="6"
name="AUTHORIZATION IDENTIFICATION RESPONSE"
class="org.jpos.iso.IF_CHAR"/>
<isofield
id="39"
length="2"
name="RESPONSE CODE"
class="org.jpos.iso.IF_CHAR"/>
<isofield
id="41"
length="16"
name="CARD ACCEPTOR TERMINAL IDENTIFICACION"
class="org.jpos.iso.IF_CHAR"/>
<isofield
id="44"
length="27"
name="ADITIONAL RESPONSE DATA"
class="org.jpos.iso.IFA_LLCHAR"/>
<isofield
id="49"
length="3"
name="CURRENCY CODE, TRANSACTION"
class="org.jpos.iso.IF_CHAR"/>
<isofield
id="60"
length="15"
name="RESERVED PRIVATE"
class="org.jpos.iso.IFA_LLLCHAR"/>
<isofield
id="100"
length="11"
name="RECEIVING INSTITUTION IDENT CODE"
class="org.jpos.iso.IFA_LLNUM"/>
<isofield
id="103"
length="19"
name="ACCOUNT IDENTIFICATION 2"
class="org.jpos.iso.IFA_LLCHAR"/>
<isofield
id="126"
length="999"
name="RESERVED PRIVATE USE"
class="org.jpos.iso.IFA_LLLCHAR"/>
</isopackager>
Notice that there is no field 5? because that is how it is supposed to be if I convert my hex to ascii it will give me this
ISO0150000700210F23A8001AE908010
which the spec is this
if I turn my primary bit map to binary it will give me this
11110010 00111010 10000000 00000001 10101110 10010000 10000000 00010000
and from that info, the field that should be active is 1,2,3,4,7,11,12,13,15,17,32,33,35,37,38,39,41,44,49,60,100,103,126
Where did I go wrong? this is the rest of my code
public synchronized Map<String, String> receiver(Socket socket) throws ISOException {
Map<String, String> response = new HashMap<>();
ISOMsg iso = new ISOMsg();
response.put("mti","0000");
try {
byte[] messageByte = new byte[socket.getReceiveBufferSize()];
DataInputStream inputByte = new DataInputStream(socket.getInputStream());
int bytesRead = inputByte.read(messageByte);
byte[] sendByte = new byte[bytesRead];
System.arraycopy(messageByte,0,sendByte,0,bytesRead);
String rawMessage = ISOUtil.hexString(sendByte);
log.info("request iso string : {}",rawMessage);
int messageLen = Integer.parseInt(rawMessage.substring(0,4),16);
log.info("message length : {}",messageLen);
String isoData = rawMessage.substring(4);
response.put("data",isoData);
// String isoData = rawMessage.substring(8,(messageLen * 2) + 8);
InputStream inputStream = getClass().getResourceAsStream("/iso-prima-msg.xml");
GenericPackager packager = new GenericPackager(inputStream);
iso.setPackager(packager);
iso.unpack(ISOUtil.hex2byte(isoData));
createDump(iso,"INCOMING");
response.put("mti",iso.getMTI());
} catch (Exception err) {
StringWriter stack = new StringWriter();
err.printStackTrace(new PrintWriter(stack));
log.error("Error handling message -> {}",stack);
createDump(iso,"INCOMING-ERROR");
}
return response;
}
I have managed to find out the answer. While https://stackoverflow.com/a/78803181/10467473 doesn't directly solve the problem but it gives me to some insight.
the main problem is from my receiver function itself. I don't need to cut the oncoming hex message before unpacking it as the hex message already start with the header itself.
Also, since in my packager xml I already state the length of my header <isopackager headerLength="12">
; I don't need to cut the header manually from my hex code.
This is my fixed function and it serves me well
public synchronized Map<String, String> receiver(Socket socket) throws ISOException {
Map<String, String> response = new HashMap<>();
ISOMsg iso = new ISOMsg();
response.put("mti","0000");
try {
byte[] messageByte = new byte[socket.getReceiveBufferSize()];
DataInputStream inputByte = new DataInputStream(socket.getInputStream());
int bytesRead = inputByte.read(messageByte);
byte[] sendByte = new byte[bytesRead];
System.arraycopy(messageByte,0,sendByte,0,bytesRead);
String rawMessage = ISOUtil.hexString(sendByte);
log.info("request iso string : {}",rawMessage);
response.put("data",rawMessage);
InputStream inputStream = getClass().getResourceAsStream("/iso-prima-msg.xml");
GenericPackager packager = new GenericPackager(inputStream);
iso.setPackager(packager);
iso.unpack(ISOUtil.hex2byte(rawMessage));
createDump(iso,"INCOMING");
response.put("mti",iso.getMTI());
log.info("CHECK ISO FIELD 33 => {}", iso.getString(33));
} catch (Exception err) {
StringWriter stack = new StringWriter();
err.printStackTrace(new PrintWriter(stack));
log.error("Error handling message -> {}",stack);
createDump(iso,"INCOMING-ERROR");
}
return response;
}