How to use IKVM and Java in Acumatica along with jar

Hello everybody,

today want to share on how you can use IKVM in Acumatica.

Imagine following scenario. You need some business logic, but that business logic is implemented in some java library, and not in C#. 

How to deal with that?

Recently I have found solution: IKVM. IKVM allows you to create dll, which you can use inside of C#, but in scope of Acumatica you may need to download one of the IKVM builds from here

I used 8.2.3 as one of the recent builds.

Step 1. Use ikvmc

For creation of dll, you may need ikvmc tool. It may look simple usage. Navigate to ikvmc, and run something like 

ikvmc -target:library -out:jackcess-4.0.5.dll jackcess-4.0.5.jar commons-lang3-3.10.jar poi-4.1.1.jar commons-logging-1.2.jar junit-4.13.1.jar

2. Versioning of IKVMC

Quite puzzling may be which exact builds to use for creation. That can be found through command 

jar xf jackcess-4.0.5.jar

and looking on pom.xml, section dependencies, and there you'll find which jar files you need to download.

3. Create class library for working with created dll.

4. In created graph/graph extension use code like below:

List<string[]> rowsClosure = new List<string[]>();
 
            try
            {
                Thread thr = new Thread(
                    t =>
                    {
                        string[] assemblyPaths = new string[]
                        {
                            @"D:\SourceCode\IKVMAccess\IKVMAccess\AccessReader.Lib\bin\Debug\IKVM.Java.dll",
                            @"D:\SourceCode\IKVMAccess\IKVMAccess\AccessReader.Lib\bin\Debug\IKVM.Runtime.dll",
                            @"D:\SourceCode\IKVMAccess\IKVMAccess\AccessReader.Lib\bin\Debug\IKVM.Runtime.JNI.dll",
                            @"D:\SourceCode\IKVMAccess\IKVMAccess\AccessReader.Lib\bin\Debug\jackcess-4.0.5.dll", // Ensure this is the .NET assembly generated by IKVMC
                        };
 
 
                        // Load each assembly
                        foreach (string path in assemblyPaths)
                        {
                            Assembly.UnsafeLoadFrom(path);
                        }
 
                        // The path to the DLL
                        string dllPath = @"D:\Source\IKVMAccess\IKVMAccess\AccessReader.Lib\bin\Debug\AccessReader.Lib.dll";
 
                        // Load the assembly
                        Assembly assembly = Assembly.UnsafeLoadFrom(dllPath);
 
                        // Get the type of the class you want to create
                        Type type = assembly.GetType("AccessReader.Lib.Reader");
 
                        // Create an instance of the class
                        object instance = Activator.CreateInstance(type);
 
                        // Prepare the parameters for the method call
                        string accessFilePath = @"c:\Vision\delay.mdb";
                        string tableName = "staff";
 
                        // Get the MethodInfo object for the method you want to call
                        MethodInfo methodInfo = type.GetMethod("ReadAllRows");
 
                        // Call the method
                        // Note: we're assuming the method is public and non-static
                        object result = methodInfo.Invoke(instance, new object[] { accessFilePath, tableName });
 
                        // passing output from executed thread to calling thread
                        lock (lockthis)
                        {
                            rowsClosure = (List<string[]>)result;
                        }
                    }
 
                    );
                thr.Start();
                thr.Join();
            }
            catch (Exception e)
            {
                PXTrace.WriteError(e);
            }

 Couple of explanations on the provided code. You can't load dll inside of your main thread, as it will not work