Open Lowcode Message

Open Lowcode message is available on Open Lowcode Github. Just head there if you want to see the code first.

Design Rationale

At the beginning of Open Lowcode adventure, I had to plan sending structured information over a network. The standard solution would be sending an XML message, but this is not satisfactory: XML messages are verbose, complex, and slow to code / decode. So I designed a light structured format with the following rationale:

  • It should be human readable: this makes dedoding much easier. This means the message is sent as text, which means accepting the 25% overhead of encoding binary files;
  • It should be compact
    • For normal messages, it should not weight much more than the payload and the message element names.
    • It should have a mode to send data in a table, weighting approximately the same thing as a CSV file
  • It should have enough information that a desynchronization between message sent and expected received message is detected immediately (wrong structures / wrong field names…)
  • It should not require to store the entirety of a message sent in memory.

Message Sample

A sample message in OLc Message (short for Open Lowcode Message) is shown below.

{
[STR1:FLD1="Content of field 1"
[SUBSTR1_1:FLD1_1="Content of field 1.1",FLD1_2=D20190805T171356]
 ]
}

Basics are:

  • Messages are delimited by curly brackets ‘{‘ and ‘}’. After sending a message, it is assumed the other party will be able to conclude an action.
  • Messages are made of structures deliminated by square brackets ‘[‘ and ‘]’. The name just after the opening square bracket is the name of the structure. If the structure contains fields, a column ‘:’ is displayed after the name of the structure
  • Then, fields are shown with a succession of NAME=VALUE, separated. If Value is a text, it is between double quotes.

Writing a message

A message is written in code in the order it will be printed: opening a message, opening a structure, declaring the fields inside… The code below is creating the message shown above.

		messagewriter.startNewMessage();
		messagewriter.startStructure("STR1");
		messagewriter.addStringField("FLD1","Content of field 1");
		messagewriter.startStructure("SUBSTR1_1");
		messagewriter.addStringField("FLD1_1","Content of field 1.1");
		messagewriter.addDateField("FLD1_2",new Date());
		messagewriter.endStructure("SUBSTR1_1");
		messagewriter.endStructure("STR1");

Reading a message

You can read a message with a very similar code to the writing. The Reader has convenience method that will check the next element you expect is indeed present, or else throw an exception.

                reader.returnNextMessageStart();
		reader.returnNextStartStructure("STR1");
		System.out.println("Content of Field 1 "+reader.returnNextStringField("FLD1"));
		reader.returnNextStartStructure("SUBSTR1_1");
		System.out.println("Content of Field 1.1 "+reader.returnNextStringField("FLD1_1"));
		System.out.println("Content of Field 1.2 "+reader.returnNextDateField("FLD1_2"));
		reader.returnNextEndStructure("SUBSTR1_1");
		reader.returnNextEndStructure("STR1");
		reader.returnNextEndMessage();

Exception Handling

Errors are managed the following way:

  • If ithe writer receives an illogical instruction, a RuntimeException is thrown. An example is trying to close a structure that was not opened. This is a development error that you should catch, as any other similar bug, at a high level in your program.
  • If the program reading the message is expecting something else than what is in the message, the framework will throw a RuntimeException.
  • If any communication error happens during writing or reading of messages, an IOException is thrown. There should probably be a place in your program where you try to recover IOException and relaunch messages
  • If a party processing a request encounters an error, it can send an error message element at any point during the sending of a message. This will generate an OLcRemoteException, that you can also catch at the appropriate level.

Sending of Compact Array

The toolset offers the possibility to send a compact data array in a format similar to CSV, i.e. easy to parse and compact. An array will look as shown in the message sample below

{
((TESTARRAY(FIELD1="O",FIELD2="I",FIELD3="X",FIELD4="S")
(T,123,X12.5,"Line 1 ")
(F,-50,X-123.5,"Line 2  ")
(T,45000,X45.5,"Line 45 --<  ") ))
}

The first line is the declaration of the fields present,s and the other lines contain the data. A compact array is delimited by a double bracket ‘((‘ and ‘))’.