rene.klomp

How to call DLL functions from a Boomi process using JNA

Blog Post created by rene.klomp Employee on Jan 19, 2017

Recently I looked into ways to call DLL functions from within a Boomi process. The idea was to use Java Native Access or JNA to call these DLL functions...

 

From Wikipedia: "Java Native Access (JNA) is a community-developed library that provides Java programs easy access to native shared libraries without using the Java Native Interface. JNA's design aims to provide native access in a natural way with a minimum of effort."

 

To build an example use case I started by putting together my own example DLL using MS Visual Studio. For this example I built a DLL using C++ containing functions that will either Add, Subtract, Multiply, or Divide two values. The resulting, extremely simple code in the MathFuncsDll.cpp file you can see in the screenshot below.

 

The corresponding MathFuncsDll.h file is actually exporting these functions using __declspec(dllexport) so they can be called externally.

 

 

 

Building this project generates the actual MathFuncsDll.dll that I copied into my local Boomi Atom that is installed on my Windows 10 laptop. I copied it into my 'C:\Boomi AtomSphere\Atom - XYZ\userlib\script' directory which I had added before in my atomw.vmoptions config file (obviously this could be any folder):

 

-Djna.library.path=C:\Boomi AtomSphere\Atom - XYZ/userlib/script

 

Furthermore, to be able to use JNA in the first place I downloaded the corresponding jar files (for the latest stable release: jna-4.2.2.jar and jna-platform-4.2.2.jar) and put them into the Atom's lib folder. These jar files can be obtained from GitHub - java-native-access/jna: Java Native Access.

 

After adding the .dll and .jar files the Atom needs to be restarted.

 

Calling these functions can be done by using Groovy scripting, either through a Data Process shape or by using it within a Map function. I have used both but for this case I am going to elaborate on the Map shape. Here I built a process that is taking a Flat File document that has 2 columns (value1 and value2). Then I map these onto a similar document that has the same two columns but added to that four columns showing the output of the four functions in the DLL:

 

 

The Message shape is just containing some sample comma separated flat file document with a couple of values:

 

 

Then more importantly the Map shape:

 

 

Here we see mapping value1 and value2 one-to-one to the output file and also providing them as input values to our DLL functions which are called from a custom scripting function in the middle of the map. First of all I defined the variables for the custom scripting function:

 

 

Here's the full Groovy script:

import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.Native;

interface IMathFuncs extends StdCallLibrary {
double Add(double a, double b);
double Subtract(double a, double b);
double Multiply(double a, double b);
double Divide(double a, double b);
}

def IMathFuncs mathFuncs =
(IMathFuncs) Native.loadLibrary("MathFuncsDll", IMathFuncs.class);

resultAdd = mathFuncs.Add(value1, value2);
resultSubtract = mathFuncs.Subtract(value1, value2);
resultMultiply = mathFuncs.Multiply(value1, value2);
resultDivide = mathFuncs.Divide(value1, value2);

 

What we see here is first of all creating an Interface (IMathFuncs) that contains the functions from the DLL that we want to use. Then I use this Interface to connect to the DLL (MathFuncsDll) and use its functions via the Native.LoadLibrary(…) function of JNA.

 

When now testing the Boomi process in my local Atom we get the following result:

 

 

Inspecting the Shape Source Data for the Stop shape (the actual output after mapping and thus calling the custom script which in its turn is calling my DLL functions) reveals the following data (note: I have configured the result values in the Flat File profile to only have two decimals):

 

 

Or downloading the original document and opening it in Excel, showing the data in columns:

 

 

We see exactly what we expect where the result of calling my DLL functions is displayed in the corresponding result columns!

 

Similarly, I have used existing Windows DLL like e.g. kernel32.dll to show it not only works for my own built custom DLL. In that case (again, it's just an example) I used:

interface Kernel32 extends StdCallLibrary {
   public void Sleep(int DURATION);
}

def Kernel32 lib = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);

lib.Sleep(5000);

 

When using this in a Data Process shape and testing it you will actual see the Boomi process pause for 5 seconds while calling the Sleep function. Obviously the last example is just a silly one that can be done in an easier way but it is just to prove my point.

 

So if you ever find yourself needing to invoke some external DLL libraries as part of a Boomi process flow, now you know you can!

Outcomes