Boomi Groovy basics

satya - 11/10/2016, 12:20:47 PM

Boomi groovy sample code

Boomi groovy sample code

Search for: Boomi groovy sample code

satya - 11/10/2016, 12:24:52 PM

Here is a sample


import java.util.Properties;
import java.io.InputStream;

for( int i = 0; i < dataContext.getDataCount(); i++ ) {
  InputStream is = dataContext.getStream(i);

  // Here is the Properties object for the current Document
  Properties props = dataContext.getProperties(i);

  dataContext.storeStream(is, props);
}

satya - 11/10/2016, 12:26:10 PM

Here is a bit more script context


import java.util.Properties;
import java.io.InputStream;
// Import any additional external Java or custom classes to be used in the script.
// BEGIN GLOBAL LOGIC //
// Perform any initialization logic. This logic will execute once
// per STEP execution, not per DOCUMENT.
// END GLOBAL LOGIC //
// Loop through the group of Documents that reached the Data Process shape.
// Note the getDataCount() method provides the count of the number of Documents
// passed into this step. This may be helpful in initialization logic above.
for( int i = 0; i < dataContext.getDataCount(); i++ ) {

  // The logic here will be executed per DOCUMENT.
  // Retrieve the Document data as an InputStream object.
  InputStream is = dataContext.getStream(i);

  // Retrieve the Document's properties a Properties object. This includes
  // Connector tracked properties, Meta Information properties, as well as
  // User Defined Document Properties.
  Properties props = dataContext.getProperties(i);


  // BEGIN PER DOCUMENT LOGIC //
  // Perform any logic to parse, inspect, manipulate, etc. the Document data
  // and properties here. This is the main part of the script.
  // END PER DOCUMENT LOGIC //
  // After performing your custom logic, you need to convert the data back
  // into an InputStream and store it to the dataContext to pass to the next
  // Process step. The number of InputStreams you store will be the number of
  // Documents passed to the next step.

  dataContext.storeStream(is, props);

} // End for-each-Document For loop

satya - 11/10/2016, 12:26:52 PM

Starting link custom scripting at Boomi

Starting link custom scripting at Boomi

satya - 11/10/2016, 12:30:20 PM

Reading from input stream


BufferedReader reader = new BufferedReader(new InputStreamReader(is));
   StringBuffer outData = new StringBuffer();
   int lineNum = 0;

   while ((line = reader.readLine()) != null) {
   if (lineNum>0) {
      String[] columns = line.split(DELIMITER);
      String someColumnValue = columns[4];
      // Perform business logic here as necessary
   }

satya - 11/10/2016, 12:30:51 PM

Putting a string back on the output


is = new ByteArrayInputStream(outData.toString().getBytes("UTF-8"));
dataContext.storeStream(is, props);

satya - 11/10/2016, 12:31:12 PM

A complete example of that


import java.util.Properties;
import java.io.InputStream;
import java.io.BufferedReader;


String LINE_SEPARATOR = System.getProperty("line.separator");
String DELIMITER = ",";

for( int i = 0; i < dataContext.getDataCount(); i++ ) {

   InputStream is = dataContext.getStream(i);
   Properties props = dataContext.getProperties(i);

   BufferedReader reader = new BufferedReader(new InputStreamReader(is));
   StringBuffer outData = new StringBuffer();
   int lineNum = 0;

   while ((line = reader.readLine()) != null) {
   if (lineNum>0) {
      String[] columns = line.split(DELIMITER);
      String someColumnValue = columns[4];
      // Perform business logic here as necessary
   }

    // Add line to output buffer including a line break at the end
    outData.append(line);
    outData.append(LINE_SEPARATOR);
    lineNum++;

   }//eof-while

   // Convert the output StringBuffer to an InputStream and store in the dataContext
   is = new ByteArrayInputStream(outData.toString().getBytes("UTF-8"));
   dataContext.storeStream(is, props);
}//eof-for

satya - 11/10/2016, 12:31:21 PM

Keep in mind All Java code is Groovy code!!!

Keep in mind All Java code is Groovy code!!!

satya - 11/10/2016, 12:31:49 PM

So if you can jigger a test harness and do most coding in Java...

So if you can jigger a test harness and do most coding in Java...

satya - 11/10/2016, 12:33:21 PM

ExecutionUtil


import com.boomi.execution.ExecutionUtil;

ExecutionUtil.setDynamicProcessProperty("DOC_COUNT", 
   String.valueOf(dataContext.getDataCount()), 
   false);

satya - 11/10/2016, 12:34:25 PM

Writing to process log


import com.boomi.execution.ExecutionUtil;
logger = ExecutionUtil.getBaseLogger();
logger.info("Processing customer: " + customerNumber);

// You can also use the 
info(), 
warning(), 
severe() and 
fine() 

methods to create entries with different log levels.

satya - 11/10/2016, 12:35:41 PM

Here is the Javadoc for ExecutionUtil class

Here is the Javadoc for ExecutionUtil class

satya - 11/10/2016, 12:37:32 PM

Key document: Here is how to simulate data context

Key document: Here is how to simulate data context

satya - 11/10/2016, 12:38:37 PM

Here is what it says

When testing outside AtomSphere, you will need to simulate the dataContext object by modifying your script to read data in from files on your local PC and write results to the console or back to disk. Groovy and Java syntax is very similar so there will be few minor syntactical changes to make when switching, most notably any private method declarations.

satya - 11/10/2016, 12:38:53 PM

There is no reason why not simulate the whole Datacontext :)

There is no reason why not simulate the whole Datacontext :)

satya - 11/10/2016, 12:40:25 PM

It would have been awesome if DataContext is an interface!!!

Doesn't look like it is!!

satya - 11/10/2016, 12:49:59 PM

Here is a simulated Datacontext if you need some sample code


package com.ai.boomi.simulated;

import java.io.InputStream;
import java.util.Properties;

//All will throw runtime exceptions
public interface IDataContext {
   //Returns the number of documents
   int getDataCount();
   
   //Return the document given its index
   InputStream getStream(int currentDocument);
   
   //Return the related document property set given the document index
   Properties getProperties(int currentDocument);
   
   //Set the document on the output side
   void storeStream(InputStream is, Properties p);
}

satya - 11/10/2016, 12:50:29 PM

These simulated code samples are preliminary.

I will post the final result once available.

satya - 11/16/2016, 4:20:22 PM

There are 3 significant observations when it comes to groovy in Boomi

1. In real time, it is not clear the performance penalty of invoking groovy and tearing it down (it that is the case) as the service or process is hit in parallel by incoming http requests. It is not clear if this penalty is 10% or 20% or 30%. Or what the impacts on average response time or maximum response time and garbage collection.

2. There are no triggers available, in my perfunctory knowledge, to optimize the code in groovy/java to say load somethings in the begining and make that available for every invocation. In servlets parlance this will be in the initialization servlets for the app server. To do this right one would need events that tell a) when a server is restarted b) when a process is deployed and undeployed etc. Note these facilities may be available when connectors are written but for pure java code this doesn't appear to be the case.

3. Further more if you want to store passwords there is no explicit way to do this but store them on local servers somewhere but then when the passwords change the servers have to be restarted. (see note 2). Items 2 and 2 are likely handled inside a connector but not available to plain java code.

These items will limit the use of groovy scripting on real time side I suspect!! But much testing is needed to see the extent of impact on scale. Some of the issues are mitigated on the batch side because the invocation of groovy is much small in comparison to the time it takes to complete a batch process. Plus you can also bear with repeating initialization for each invocation which will also address the password maintenance issue to an extent.

All of this is again addressing that 5% of cases where one has to drill down into a groovy script otherwise utilizing the the 95% of native Boomi capability in cases usual.