MT Builder (Java to SWIFT)

Functionality to create a new SWIFT message by populating Java objects, and writing the result in SWIFT FIN format

The creation of a new message basically consists of creating an MT object for the specific message type, and the subsequent addition of fields in an orderly manner.

The order of the fields is very important and should be done accordingly to the standard, the model does not prevent creating incorrect content (Standard compliance validation can be checked with Prowide Integrator).

The following sections provides explanation by examples, creating messages in different common scenarios:

Creating a message with MT classes

The following example shows how to create a new MT103 message using the MT and Field helper classes. This is the easiest and recommended way to create a new message from scratch because the API will automatically fill mandatory header information with proper default values.

The first step is to create the specific MT object and set its general attributes:

final MT103 m = new MT103();
m.setSender("FOOSEDR0AXXX");
m.setReceiver("FOORECV0XXXX");

At this point all message blocks are initialized, and by default the message will be an outgoing message (input to SWIFT) with normal priority.

The next step is adding the message fields. For simple fields the final value can be directly provided as a single String value, and for more complex fields with several subfields (components) the Field helper classes may be used.

m.addField(new Field20("REFERENCE"));
m.addField(new Field23B("CRED"));

Field32A f32A = new Field32A()
.setDate(Calendar.getInstance())
.setCurrency("EUR")
.setAmount("1234567,89");
m.addField(f32A);

Field50A f50A = new Field50A()
.setAccount("12345678901234567890")
.setBIC("FOOBANKXXXXX");
m.addField(f50A);

Field59 f59 = new Field59()
.setAccount("12345678901234567890")
.setNameAndAddress("JOE DOE");
m.addField(f59);

m.addField(new Field71A("OUR"));

Finally the message() method converts the object into its SWIFT representation:

System.out.println(m.message());

The output of the above example is:

{1:F01FOOSEDR0AXXX0000000000}{2:IFOORECV0XXXXN}{4:
:20:REFERENCE
:23B:CRED
:32A:1303EUR1234567,89
:50A:/12345678901234567890
FOOBANKXXXXX
:59:/12345678901234567890
JOE DOE
:71A:OUR
-}

Notice for instance how field 50A was serializing into a proper value including the slash prefix for the account number and the line feed between the account and the BIC code.

/12345678901234567890 [CRLF]
FOOBANKXXXXX

The same procedure is used to create any type of message, changing the MT103 by any other available implementation.

Creating inner sequences

For more complex messages where fields must be contained in sequences (or sub blocks) some helper API is also provided by the message model. The following example shows how to append a General Information sequence A to an MT542:

SequenceA A = MT542.SequenceA.newInstance(
Field20C.tag(":SEME//2005071800000923"),
Field23G.tag("NEWM"));
m.append(A);

For boundary based sequences the opening and closing fields 16R and 16S will be automatically included.

When the message is converted to FIN, the above sample code will generate the following SWIFT content:

:16R:GENL
:20C::SEME//2005071800000923
:23G:NEWM
:16S:GENL

Notice sequences should be appended in the correct order, as well as fields inside the sequence block. The API will not control the correctness of the content being generated. The main reason to use this helper sequences API is the constraint provided in the MTnnn classes where only the proper SequenceX inner classes will exist, this way you can rest assure that the appended sequences are part of the specific message type.

Nested sequences can be also created with a similar API. The following example creates a complete MT517 with nested sequences A and A1:

MT517 mt = new MT517().append(MT517.SequenceA.newInstance(new SwiftTagListBlock()
    .append(Field20C.tag(":SEME//2005071800000923"))
    .append(Field23G.tag("NEWM/CODU"))
    .append(Field95P.tag(":AFFM//MGTCDE55"))
    .append(MT517.SequenceA1.newInstance(
        Field13A.tag("LINK//515"),
        Field20C.tag(":RELA//FRTJ12CONF0002")))
    .append(MT517.SequenceA1.newInstance(
        Field13A.tag("LINK//512"),
        Field20C.tag(:RELA//FRTJ12CONF0003)))
    ));

Notice how in order to append both Field and sequence objects to the container A sequence, we create a generic SwiftTagListBlock on the fly. The created FIN content for the above snippet is:

{1:F01TESTUS00AXXX0000000000}{2:I517TESTUS00XXXXN}{4:
:16R:GENL
:20C::SEME//2005071800000923
:23G:NEWM/CODU
:95P::AFFM//MGTCDE55
:16R:LINK
:13A:LINK//515
:20C::RELA//FRTJ12CONF0002
:16S:LINK
:16R:LINK
:13A:LINK//512
:20C::RELA//FRTJ12CONF0003
:16S:LINK
:16S:GENL
-}

Creating a message with specific header content

To create headers with special information, the block's API can be accessed directly. The following example illustrates how to create a message using the low level model layer to create specific headers, overriding the ones created by default in the MT103 constructor.

MT103 m = new MT103();

SwiftBlock1 b1 = new SwiftBlock1();
b1.setApplicationId("F");
b1.setServiceId("01");
b1.setLogicalTerminal("BICFOOYYAXXX");
b1.setSessionNumber("1234");
b1.setSequenceNumber("123456");
m.getSwiftMessage().setBlock1(b1);

SwiftBlock2Input b2 = new SwiftBlock2Input();
b2.setMessageType("103");
b2.setReceiverAddress("BICFOARXXXXX");
b2.setDeliveryMonitoring("1");
m.getSwiftMessage().setBlock2(b2);

m.getSwiftMessage().setBlock3(new SwiftBlock3());
m.getSwiftMessage().getBlock3().addTag(Field113.tag("NOMT"));
m.getSwiftMessage().getBlock3().addTag(Field108.tag("P22ABCD43C6J3XYZ"));

In the above example a new and empty message object is created. The basic header (block 1) information is set with specific information, the application header (block 2) is created directly from a suitable string value with all its corresponding attributes pre set, and final an optional user header (block 3) is constructed by adding its tags.

Since the MTnnn classes uses a SwiftMessage instance inside, both level API can be combined; the MTnnn and Fieldnnn classes can be use to create the main content of the message and then the SwiftMessage object can be accessed to add or change specific header or trailer information.

Adding a message trailer block

In most situations there is no need to create the trailer block because it will be added automatically by the FIN interface. However, the API allows the creation of the trailer block as well as any other optional message block as follows:

MT103 m = new MT103();
SwiftBlock5 block5 = new SwiftBlock5();
block5.addTag(new Tag("MAC", "00000000"));
block5.addTag(new Tag("PDE", ""));
m.getSwiftMessage().addBlock(block5);

The resulting block when the object is serialized to FIN will be:

{5:{MAC:00000000}{PDE:}}

Adding optional blocks

Analogously to the description for Block 5, the same API can be used to create the optional User Header Block (block 3) or to add additional trailers.

In particular for the block 3, since it is becoming more used a new SwiftBlockBuilder helper class was introduced to ensure only valid fields are added to the block, and that fields are added in proper order.

For backward compatibility we have kept the SwiftBlock3 structure which is a List but the new builder provides specific setters for each available block 3 field. The builder instance is created directly from the block and works as a decorator on the underlying list of tags.

SwiftBlock3 b = new SwiftBlock3 ();
b.builder()
  .setField121(new Field121("value121"))
  .setField106(new Field106("value106"))
  .setField165(new Field165("value165"))
  .setField106(new Field106("finalValue106"))
  .setField108(new Field108("value108"));

Regardless of the setField calls order or repetition, the internal block 3 will be always consistent, and in the above example will produce this output:

{3:{108:value108}{106:finalValue106}{121:value121}{165:value165}}

The same applies when the message is created with an MT class. For instance if you need to add the MUR field 108 you can use the following:

MT103_STP mt = new MT103_STP(sender, receiver);
mt.getSwiftMessage().getSwiftBlock3().builder().setField108(“value108”);

And the output will be:

{3:{108:value108}{119:STP}{121:value121}}

Notice, fields 119 and 121 were automatically added when the MT instance was created, and the manually added field 108 was placed in the correct position in the existing block 3.

Finally this examples appends an optional application trailer block:

SwiftBlockUser blockUser = new SwiftBlockUser("S");
blockUser.addTag(new Tag("SAC", ""));
blockUser.addTag(new Tag("COP", "P"));
m.getSwiftMessage().addBlock(blockUser);