Skip to content

Parser (FIN MT to Java)

The parser provides functionality to convert SWIFT messages FIN text into the Java message model

By doing this, you can work with SWIFT messages focusing on the data and not having to deal with low level syntax details.

The parser always performs a best effort heuristic to parse the message even if it is not well formed. All the information is read and put in a suitable object of the message model regardless of the message being SWIFT compliant.

The parser functionality has different entry point depending on the use case:

Generic processing of unknown messages

In situations where the message type is unknown, the easiest and recommended way to read and parse messages is by means of the abstract class AbstractMT. This class provides static methods to parse an unknown message from a String or InputStream.

For example consider the following SWIFT message example:

    {1:F01BANKDEFMAXXX2039063581}{2:O1031609050901BANKDEFXAXXX89549829458949811609N}{4:
    :20:007505327853
    :23B:CRED
    :32A:050902JPY3520000,
    :33B:JPY3520000,
    :50K:EUROXXXEI
    :52A:FEBXXXM1
    :53A:MHCXXXJT
    :54A:FOOBICXX
    :59:/13212312
    RECEIVER NAME S.A
    :70:FUTURES
    :71A:SHA
    :71F:EUR12,00
    :71F:EUR2,34
    -}

Assuming the message is in a String variable "fin", the following code will parse the FIN message into a message object object, where several getters are available to read message header information.

AbstractMT msg = AbstractMT.parse(fin);
String sender = msg.getSender();
String type = msg.getMessageType();

Even though the message type is unknown the returned object will be parsed into its specific MTnnn model object. So once the message type is known a simple cast is enough to access detail information of the text block for reading or manipulating its content. In the example:

System.out.println(msg.getMessageType());

if (msg.isType(103)) {
        MT103 mt = (MT103) msg;
        // print the message reference

        System.out.println("Reference: "+mt.getField20().getValue());

        // read components of a specific field
        Field32A f = mt.getField32A();
        Calendar date = f.getComponent1AsCalendar();
        Number  amount = f.getComponent3AsNumber();
}

Notice MTnnn classes provide API that is exclusively related to the fields that can be present in each message type.

Parsing an unknown message for persistence

While in the context of a parsing an unknown message, if the ultimate requirement is to read just headers information, persist the message into a database or to process large bursts of messages, the recommended way to read and parse messages is by means of the MtSwiftMessage class. This class also implements several ways to create the message instance from String, InputStream; but only header information is read and the model is kept generic after the parse.

Assuming the message is in a String or InputStream variable "fin" , the following code will parse the FIN message into a MtSwiftMessage object, and getters are used to access message header information.

MtSwiftMessage msg = MtSwftMessage.parse(fin);
String sender = msg.getSender();
String type = msg.getMessageType();

The MtSwiftMessage is a lightweight representation of the message where only the header and trailer blocks are parsed and modeled, while the text block (the actual business payload) is kept in its raw unparsed format.

Specializing an unkown message

The above way of reading messages is the most efficient in terms of performance and it is useful to process large burst of messages; but it is limited for content manipulation.

However, once the message object is created and properly identified, it can be specialize to access the specific text block content, for example:

MT103 mt = new MT103(msg);
Field32A f = mt.getField32A();
Calendar date = f.getComponent1AsCalendar();
Number amount = f.getComponent3AsNumber();

Notice that specializing a generic message from an AbstractMT requires only a cast to the specific MTnnn, while doing the same from an MtSwiftMessage requires a constructor.

Another important thing to know when deciding to use the AbstractMT or the MtSwiftMessage is that parsing by an AbstractMT implies that the message type can be determined from the block 2 header, that's because internally the parser will create the corresponding message type object (MTnnn). While parsing by an MtSwiftMessage does not impose anything to the message content, that could be malformed or incomplete and the message object will be created anyway.

Specific processing of a known message type

When the message to parse is known, the specific model class can be used directly to parse and read the content. For example:

        MT103 model = MT103.parse(fin);
Where the fin parameter can be a String or InputStream with the message in its FIN format, and the parsing can be called using the static parse method (as in the example) or by an MTnnn constructor.

Once the object is created all its specific content can be read using getters for specific sequences and fields.

Parsing message with ACK

There is a frequent misunderstanding of the FIN messages format when the actual message is preceded by a system ACK, and the expected behavior of Prowide Core parser when reading such messages.

The following example is actually a service message for ACK, followed by the original MT940 sent:

    {1:F21FOOLHKH0AXXX0304009999}{4:{177:1608140809}{451:0}}{1:F01FOOLHKH0AXXX0304009999}{2:O9401609160814FOOLHKH0AXXX03040027341608141609N}{4:
    :20:USD940NO1
    :21:123456/DEV
    :25:USD234567
    :28C:1/1
    :60F:C160418USD672,
    :61:160827C642,S1032
    :86:ANDY
    :61:160827D42,S1032
    :86:BANK CHARGES
    :62F:C160418USD1872,
    :64:C160418USD1872,
    -}{5:{CHK:0FEC1E4AEC53}{TNG:}}{S:{COP:S}}

If you pass the above content to the parse method, by default the parser will get the first FIN message found in the file (the ACK service message), leaving the rest of the text into the UnparsedTextList structure.

This is just fine when reading plain user to user messages, but when the message is preceded by a service message as in the example, the resulting parsed object may not be the expected one.

When dealing with this scenario it is the user responsibility to check whether the message is a service message or not, and proceed accordingly, depending on the particular use case and application needs.

If you are trying to match and process the ACK/NAK notifications you may be interested on the service message. However, if this is the way you receive the messages from the SWIFT interface and you need the actual user message following the ACK, then you have to do something else.

The following example will parse the FIN content, check for the service id, and if it is a system message it will then gather the actual MT from the unparsed content:

SwiftMessage sm = SwiftMessage.parse(fin);
if (sm.isServiceMessage()) {
    sm = SwiftMessage.parse(sm.getUnparsedTexts().getAsFINString());
}

At this point the sm variable will contain the actual user to user message, regardless if it was preceded by and ACK.

For more information on the ACK/NAK structure see Processing ACK/NAK.

Direct usage of the SwiftParser

Finally, the actual parser implementation class is another option to translate a raw message in its Java model object.

SwiftMessage m = (new SwiftParser()).parse(fin);
Direct usage of the SwiftParser class is discouraged but in may be useful on certain conditions where the lenient mode of the parser must be explicitly controlled by your application.

The result of the parser is the backbone model implemented by the SwiftMessage class. So the parser will basically split the message content into the three primary elements that defines an MT message; the message itself, it's blocks, and the tag (or fields) inside each block.

Reading fields like simple tuples of name and value makes the parser very efficient, while additional content parsing can be done with the message model in a following step.

For the example, the following code can be use to gather some fields of the parsed message using the generic low level model:

String val32a = m.getBlock4().getTagValue("32A"); //get a simple value tag
String[] list71 = m.getBlock4().getTagValues("71F"); //get a repeated value tag
The "val32a" String will contain the value "050902JPY3520000," and "list71" will contains a list of String with values "EUR12,00" and "EUR2,34".

The SwiftBlock4 object basically contains an ordered List of fields found content body of the SWIFT message and provides several API to manipulate and get the tags individually or by sub blocks. At this API level the message body can be think of as a text string, where instead of characters we found message fields and we can get for example all Tags before a given one, Tags between boundaries, etc.. This API is the base foundation of the high level Sequences API.