Skip to Content
Author's profile photo Bram Keijers

Pretty print debug messages using Groovy script


The script explained in this column is intended for development and debug purposes only, it is not intended for production deployed Iflows. As explained in this post storing payload logs in the Message Process Log can cause performance issues and, in worst case scenario’s, out of memory exceptions. So be careful when using this script, use a debug flag as explained in the Iflow chapter.


Payload logging is an important aspect of integration. It will give you insight in the content of input-, intermediate- and output messages which will help in creating, altering and maintaining the integration flow. When looking at payload logging approaches I’ve found this post covering the basics. However, there are some additional requirements which will make our life easier when logging:

  • Parameterize the script: we want to set the title and other log parameters dynamically. In this way we only need one logging script
  • Pretty print message content: we want to make the messages readable
  • Completeness: if there is no input message to log we want to switch to the exception message

In the remainder of this blog I will explain how I extended the example script to adhere to these requirements, resulting in a clearer message processing log.

The logging script

Input parameters

The script relies on the following parameters:

  • logTitle: the header of the log message details
  • logType: the type of input message we present to the logging script
  • ErrorMessage: parameter which holds the exception message when used in exception sub-processes

Message formats

switch statement is used to format the message based on the given type. The following message types are supported:


The static serialize method from the  XmlUtil class is used to format the message. As an extra step a newline is set after the XML tag using the replaceAll method and a regular expression, $1 denotes the match in the replacement pattern. I think it improves the readability of the message, consider it a personal preference.


The JsonOutput class contains static method prettyPrint which formats the message. The input message is parsed with the JsonSlurper class in order to ensure correct format. The iterator is used to produce the correct indentation.


No formatting is applied since most of the CSV messages are already readable. Alternatively, you can replace separators characters to improve readability with the replaceAll and a regular expression, e.g. replace the field separator with a tab to improve readability.


The default text is word wrapped using the regular expression (.{100})(\s+|\Z). After every 100 characters ending with one or more spaces or the end of a string we apply a new line. Be aware of the backslash escaping when applying this expression.

Also, note that if there is not body message we attempt to access the exception message. We make use of the ternary operator. Alternatively the elvis operator can be used, it’s a matter of personal preference.

Logging action

Before we actually log the message we check if the required input parameters are filled. If this is not the case we will log a warning as title but still log the body message.

Usage in Iflows

Below an example implementation of the script. At the start of the Iflow we set the debug property to true if we want to log debug messages. If the debug property is set to true the properties are set and the message is logged. Alternatively, a local integration process can be used to hold the router and logging steps.  I also use the script in the exception subprocess to log exceptions. Be careful with outputting messages though, you do not want to overload you tenant.

The next image displays the conditions for the router:


The parameter setup is displayed in the image below:

The next image displays the different log messages. The enumeration corresponds to various processing steps in the Iflow. This approach will limit debug time in case of an error message in the log, you can retrace the part of the flow where the error originated.

Below the output of the mesages is shown*.





*Message content is either self-created or publicly available.


The script itself:

import java.util.HashMap;
import groovy.xml.*;
import groovy.json.*;
import java.util.regex.*;

def Message processData(Message message) {
    def body = message.getBody(java.lang.String) as String;
    def properties = message.getProperties();
    def messageLog = messageLogFactory.getMessageLog(message);
	def logTitle = properties.get("logTitle");
	def logType = properties.get("logType");
	def exceptionMessage = properties.get("ExceptionMessage");
    String logMessage = "";
    String logMessageType = "text/plain";
     switch(logType.toLowerCase()) {            
         //There is case statement defined for 4 cases 
         // Each case statement section has a break condition to exit the loop 
         case 'xml': 
            XmlUtil xmlUtil = new XmlUtil();
    		def xmldoc = new XmlParser().parseText(body);
    		def serialized = XmlUtil.serialize(xmldoc);
    		serialized = serialized.replaceAll('<\\?xml version="1.0" encoding="UTF-8"\\?>', '<\\?xml version="1.0" encoding="UTF-8"\\?> \n');
    		logMessage = serialized;     
         case 'json': 
          	def json = new JsonSlurper().parseText(body);
          	json.each { 
			  logMessage = logMessage + JsonOutput.prettyPrint(JsonOutput.toJson(it));
         case 'csv':
         	logMessage = body;
            String defaultMessage = body ? body: exceptionMessage;
           	logMessage = defaultMessage.replaceAll("(.{100})(\\s+|\\Z)","\$1\n");
      body = logMessage;
    if(messageLog != null){
    	if(logTitle != null && logMessage != null && logMessageType != null){
        	messageLog.addAttachmentAsString(logTitle, logMessage, logMessageType);
 	    	messageLog.addAttachmentAsString("Warning: one of required log parameters not set", "logTitle: "+logTitle+" logMessage: " + logMessage + "logMessageType: " +logMessageType+ "\n \n"+ body, 'text/plain');
    return message;


Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Gayathri Natarajan
      Gayathri Natarajan



      I have tried the above script to format xml, But its not working. It is providing the same xml format as provided in the input.

      Any suggestions please

      Author's profile photo Bram Keijers
      Bram Keijers
      Blog Post Author

      Hello Gayatri,

      Thank you for your interest in the logging script! The script will not modify the payload in the integration flow, it will only create the attachment with formatting.

      If you would like to format the message in the integration itself you can either add a message.setBody(serialized) to the XML case or create a separate script that does this.

      Note that it is not required for the integration to successfully process the message in the integration. The formatting is only to make the log message more readable for the user.

      If you have any additional questions please do let me know.



      Author's profile photo Gayathri Natarajan
      Gayathri Natarajan

      Hi Bram,

      1. message.setBody(serialized) to the XML - tried this and its working
      2. *Note that it is not required for the integration to successfully process the message in the integration. The formatting is only to make the log message more readable for the user.

      But point 2 is not suitable for XML to JSON converter in CPI,

      -> while converting below XML to JSON, its considering the value as "/n" instead of "", Which is incorrect














      Author's profile photo Bram Keijers
      Bram Keijers
      Blog Post Author

      Hi Gayathri,

      The input XML contains a newline as value, that is why the JSON is showing this value.
      You can filter or replace this value either with a message mapping and using the replace function for example. Or you can create a script to replace the value on the JSON output. For the last part be sure to check out groovy lang website, .


      Good luck!



      Author's profile photo Gayathri Natarajan
      Gayathri Natarajan

      Thanks Bram