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