Creating Custom IsoMessage using j8583

In the Transformer of Creating ISO8583 Server using Spring Integration and Creating ISO8583 Client using Spring Integration, there is a class called CustomIsoMessage. This class is extending IsoMessage in the j8583 library. The main purpose of this class is to print readable log of the ISO8583 Message for example:

This is inspired by the jPOS Logger that prints ISO8583 Message on XML Format. Although, j8583's IsoMessage has debugString method that returns a string representation of the message, it's hard to read single ISO8583 Message string compared to parsed ISO8583 Message.

Below is example of IsoMessage debugString results:


0800822000004090000104000000000000010403082541584020071.1.1.1T-4455661401:01:01:01:0117FA6FBCDFF0A09F3012A7E20C18900ED0F

And below is custom iso message log look like:


=====OUTGOING ISOMSG=====
CONNECTION ID	T-445566584020
REMOTE ADDRESS	127.0.0.1:20101
TIMESTAMP	2025-04-03T08:25:41.41+0700
MTI	[0800]
DE-7	[0403082541]
DE-11	[584020]
DE-34	[1.1.1.1]
DE-41	[T-445566]
DE-44	[01:01:01:01:01]
DE-64	[17FA6FBCDFF0A09F]
DE-70	[301]
DE-128	[2A7E20C18900ED0F]
=====OUTGOING ISOMSG=====


=====INCOMING ISOMSG=====
CONNECTION ID	T-445566584020
REMOTE ADDRESS	127.0.0.1:20101
TIMESTAMP	2025-04-03T08:25:41.41+0700
MTI	[0810]
DE-7	[0403082541]
DE-11	[584020]
DE-34	[1.1.1.1]
DE-39	[00]
DE-41	[T-445566]
DE-44	[01:01:01:01:01]
DE-64	[8478DBA646806115]
DE-70	[301]
DE-128	[41B2B2AB20DD0391]
=====INCOMING ISOMSG=====

Okay, let's start with the implementation. First of all, we have to define MessageFactory Bean to create and parse the ISO8583 Message


@Bean
public MessageFactory<CustomIsoMessage> messageFactory() throws IOException {
	MessageFactory<CustomIsoMessage> messageFactory = new MessageFactory<CustomIsoMessage>() {
		@Override
		protected CustomIsoMessage createIsoMessage(String header) {
			return new CustomIsoMessage(header);
		}
	};
	messageFactory.setAssignDate(true);
	ConfigParser.configureFromUrl(messageFactory, new File("config/j8583.xml").toURI().toURL());
	return messageFactory;
}

Above code will create messageFactory Spring’s Bean with CustomIsoMessage as a result of create and parse message, please note that we need to override createIsoMessage method so that messageFactory can return CustomIsoMessage instead of IsoMessage instance.

The setAssignDate method indicates messageFactory to set bit 7 (Transmission Date Time) to current date time.

And the most important part is setting the message configuration path used by messageFactory. By default, messageFactory has a setConfigPath method. This method will call ConfigParser.configureFromClasspathConfig that will search config files in the classpath. In some case, we want to put the configuration message outside of the classpath, to do that we need to call ConfigParser.configureFromUrl instead. Another option is ConfigParser.configureFromReader, this will read configuration messages from java.io.Reader instance.

Below is the implementation of CustomIsoMessage: The dumpField method is used to format ISO8583 Message into each data element key and value.


import java.io.Serializable;
import org.apache.commons.lang3.time.DateFormatUtils;
import com.solab.iso8583.IsoMessage;
import com.solab.iso8583.IsoValue;


public class CustomIsoMessage extends IsoMessage implements Serializable {
	private static final long serialVersionUID = 1L;
	public CustomIsoMessage(String header) {
		super(header);
	}
	public String dumpField(boolean incoming, String msgKey, String remoteIpAddress, String remotePort,
			Long timestamp) {
		String direction = incoming ? "INCOMING":"OUTGOING";
       StringBuilder sb = new StringBuilder("\n");
       sb.append("====="+direction+" ISOMSG=====\n");
       sb.append("MESSAGE ID\t"+msgKey);
       sb.append("\n");
       sb.append("REMOTE ADDRESS\t"+remoteIpAddress+":"+remotePort);
       sb.append("\n");
       sb.append("TIMESTAMP\t"+DateFormatUtils.format(timestamp, "yyyy-MM-dd'T'HH:mm:ss.ssZ"));
       sb.append("\n");
       sb.append(String.format("MTI\t[%04x]", getType()));
       sb.append("\n");
       //Fields
       for (int i = 2; i < 129; i++) {
           IsoValue<?> v = getField(i);
           if (v != null) {
           	sb.append("DE-"+i);
               String desc = v.toString();
               sb.append("\t[");
               sb.append(desc);
               sb.append("]\n");
           }
       }
       sb.append("====="+direction+" ISOMSG=====\n");
       return sb.toString();
	}
}

And the last part is creating a new CustomIsoMessage instance: we simply call messageFactory.newMessage(type) method to create a new CustomIsoMessage instance, this will set message type and transmission date time


@Autowired
private MessageFactory<CustomIsoMessage> messageFactory;


protected CustomIsoMessage createEchoMsg(String terminalCode, String macAddress, String version) throws Exception {
	CustomIsoMessage requestMsg = messageFactory.newMessage(0x800);
	requestMsg.setField(41, new IsoValue<String>(IsoType.ALPHA, "12345678", 8));
	requestMsg.setField(70, new IsoValue<String>(IsoType.ALPHA, "301", 3));
	return requestMsg;
}

That's all about Creating Custom IsoMessage using j8583, you can check the complete source code on Github. Hope this helps.

Comments