Question
· Mar 21, 2018

Problems encountered with Java Gateway

Problems encountered with Java Gateway

I am writing a framework for use on the Java Gateway. The role of the framework is:

1. Import the framework jar file into ensemble studio (test completed);
2. In the framework jar, handle the related functions of the remaining jar files (the rest of the jar files are written by colleagues).

The general idea is as follows:

Send: Ensemble Java Gateway -> Framework Jar -> Plugin Jar (colleagues write, processing data).
Returns: Plugin Jar (processed return data) ->Framework Jar->Ensemble Java Gateway.

The problems I encountered were:

I refer to gson and Bouncy Castle in Plugin Jar, but only one (gson or Bouncy Castle) can be loaded when running.

How can I solve this problem, my call in ensemble is as follows:

/// d ##class(PRD.Test).OnProcessInput()
ClassMethod OnProcessInput()
{
  Set val = 0
  Set gateway = ##class(%Net.Remote.Gateway).%New()
  // Below is the port and connection address.
  Do gateway.%Connect("127.0.0.1", 55555)
  // The following EnterTestClass must match the Java class name.
  Set javaObj = ##class(test.Main).%New(gateway)
  // The following enter is the public static method in the Java class.
  Set val = javaObj.run(gateway,"testdemo.jar","test.EnterTestClass","generatorPassword")
  Set val = javaObj.run(gateway,"testdemo.jar","test.EnterTestClass","uuid")
  w val,!
}

In the Java framework:

/**
 * Inherit URLClassLoader to load the jar file
 *
 * @Version: 2018/3/16 15:18
 */
Public class MyClassLoader extends URLClassLoader {
    Public MyClassLoader(URL[] urls) {
        Super(urls);
    }

    Public MyClassLoader(URL[] urls, ClassLoader parent) {
        Super(urls, parent);
    }

    Public void addJar(URL url) {
        this.addURL(url);
    }
}

Load the jar tool:

Import org.slf4j.Logger;
Import org.slf4j.LoggerFactory;

Import java.io.File;
Import java.lang.reflect.Method;
Import java.net.URL;
Import java.net.URLClassLoader;
Import java.util.ArrayList;
Import java.util.List;

/**
 * jar file loading tool class.
 *
 * @Version: 2018/3/15 16:42
 */
Public class LoadJarUtil {

    Private static final Logger logger = LoggerFactory.getLogger(LoadJarUtil.class);

    Private LoadJarUtil() {
    }

    Private static LoadJarUtil loadJarUtil = null;

    /**
     * Class loader for loading jar files.
     */
    Private static MyClassLoader classLoader = null;

    /**
     URLURLLoader's addURL method
     */
    Private static Method addURL = initAddMethod();

    Public MyClassLoader getMyClassLoader() {
        Return classLoader;
    }

    Public static LoadJarUtil getInstance() {
        If (loadJarUtil == null) {
            loadJarUtil = new LoadJarUtil();
        }
        //
        If (classLoader == null) {
            URL[] urls = new URL[]{};
            classLoader = new MyClassLoader(urls);
        }
        Return loadJarUtil;
    }

    /**
     * Initialization method
     */
    Private static final Method initAddMethod() {
        Try {
            Logger.info ("initialize JAR package loader...");
            Method add = URLClassLoader.class
                    .getDeclaredMethod("addURL", new Class[]{URL.class});
            add.setAccessible(true);
            Return add;
        } Catch (Exception e) {
            Logger.error("Initial JAR package loader failed, failure reason:" + e.getMessage());
        }
        Logger.error("initialize JAR package loader failed, unknown cause of failure");
        Return null;
    }

    /**
     * Loop through the directory to find out all JARs
     */
    Private final void loopFiles(File file, List<File> files) {
        If (file.isDirectory()) {
            Logger.info("[{}] traverses the specified path and searches for all jar files", file.getAbsolutePath());
            File[] tmps = file.listFiles();
            For (File tmp : tmps) {
                loopFiles(tmp, files);
            }
        } Else {
            If (file.getAbsolutePath().endsWith(".jar")) {
                Files.add(file);
            }
        }
    }

    /**
     * <pre>
     * Load JAR file
     * </pre>
     *
     * @param file
     */
    Public final void loadJarFile(File file) {
        Try {
            Logger.info("[{}] loads the jar file...", file.getAbsolutePath());
            // classLoader.addJar(file.toURI().toURL());
            addURL.invoke(classLoader, new Object[]{file.toURI().toURL()});
        } Catch (Exception e) {
            Logger.error("[{}] failed to load jar file, failure reason: %s", file.getAbsolutePath(), e.getMessage());
        }
    }

    /**
     * <pre>
     * Load all JAR files from a directory
     * </pre>
     */
    Public final void loadJarPath(final String jarFilePath) {
        Logger.info("[{}] loads all jar files from the specified directory.", jarFilePath);
        List<File> files = new ArrayList<File>();
        File lib = new File(jarFilePath);
        loopFiles(lib, files);
        For (File file : files) {
            loadJarFile(file);
        }
        Logger.info("[{}] loads all jar files from the specified directory successfully.", jarFilePath);
    }

}

(Framework)Main: execution method:

/**
     * Load the Jar file and read Class, call the method and get the return value (if any).
     *
     * @param pluginJarName jar file name.
     * @param className class name to call
     * @param methodName method name
     * @param array of array parameters (does not deal with specific types, all handled as String.)
     * @return
     */
    Public static Object run(final String pluginJarName, String className, String methodName, final Object[] array) {
        Logger.info ("The log module is loaded...");
        Logger.info ("Jar package needed to load the system...");
        LoadJarUtil.getInstance().loadJarPath(Constats.getConfigPath() + PropertiesUtil.getInstance().readKeyValue(Constats.JARLIBPATH));
        Logger.info ("Jar Package Required for Loading System...");
        Logger.info ("Start execution program: [jar file name: {}], [file name: {}], [method name: {}], [parameter list: {}]", pluginJarName, className, methodName, Arrays.toString(array));
        // // Custom ClassLoader to load jar file
        MyClassLoader classLoader = LoadJarUtil.getInstance().getMyClassLoader();
        Object result = null;
        Try {
            // Load the jar file for a specific path
            Logger.info ("Start loading jar files...");
            classLoader.addJar(new File(Constats.getConfigPath() + PropertiesUtil.getInstance().readKeyValue(Constats.JARPLUGPATH) + pluginJarName).toURI().toURL());
            // dynamically load the class file of a particular class in the jar file
            Class<?> clazz = classLoader.loadClass(className);
            If (null != array && array.length > 0) {
                Class<?>[] methodType = new Class[array.length];
                For (int i = 0; i < array.length; i++) {
                    methodType[i] = String.class;
                }
                Logger.info("Start calling the specified method and passing in parameters...");
                // Get the specific method to be called getName(String xx)
                Method method = clazz.getMethod(methodName, methodType);
                //Call the method to get the return value of the method.
                // Create an instance of the reflection class first, that is, the method that calls the class may not be statically statically decorated.
                Result = method.invoke(clazz.newInstance(), array).toString();
            } Else {
                // No parameter, no return value
                Logger.info("Start calling the specified method and passing in parameters...");
                Method methodD = clazz.getDeclaredMethod(methodName);
                Result = methodD.invoke(clazz.newInstance());
            }
        } Catch (Exception e) {
            e.printStackTrace();
            Logger.error("Execute Jar file exception, exception message:[{}],\nDetailed message:--", e.getMessage());
        } finally {
            // //Close class loader
            Try {
                classLoader.close();
            } Catch (IOException e) {
                Logger.error("Exception closing class loader, exception message: [{}]", e.getMessage());
            }
        }
        Logger.info("Execution result:{}", result);
        Logger.info ("execution of the specified Jar file");
        Return result;
    }

Plugin Jar:

Import java.io.BufferedWriter;
Import java.io.File;
Import java.io.FileWriter;
Import java.io.IOException;
Import java.security.Security;
Import java.time.LocalDateTime;
Import java.util.Map;
Import java.util.UUID;

Import com.google.gson.Gson;
Import com.google.gson.reflect.TypeToken;
Import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
* Ensemble connection Java class example.
*
* @Version: 2018/3/15 12:13
*/
Public class EnterTestClass {

Private static final String STATICFILEPATH = "D:\\EnterTestClass.txt";

/**
* Generate password message.
* <p>
* Parameters have a return value.
*
* @param name
* @param password
* @return
* @throws IOException
*/
Public String generatorPassword() throws IOException {
Security.addProvider(new BouncyCastleProvider());
String name="test";
String password="-demo";
String passnew = name + password;
User user = new User(name, password);
String result = "[ generatorPassword ] :" + LocalDateTime.now().toString() + ", method parameter [user:" + name + ", password:" + password + "], user output toString():" + user.toString() + ", generated password:" + password + org.bouncycastle.util.encoders.Hex.toHexString(passnew.getBytes());
Write(result);
Return result;
}

/**
* Only write messages to the file system.
* <p>
* No parameters, no return value.
*
* @throws IOException
*/
Public void writeMessage() throws IOException {
Write("[ writeMessage ] :" + LocalDateTime.now().toString() + "Generated data message.");
}

/**
* Write file messages, do not call.
*
* @param text
* @throws IOException
*/
Private void write(String text) throws IOException {
File file = new File(STATICFILEPATH);
If (!file.exists()) {
Try {
file.createNewFile();
} Catch (IOException e) {
e.printStackTrace();
}
}
BufferedWriter bf = new BufferedWriter(new FileWriter(file.getAbsoluteFile()));
Bf.append(text);
Bf.close();
}

/**
* Each call returns a different uuid. It writes a file message to the file system.
*
* @return
* @throws IOException
*/
Public String uuid() throws IOException {
File file = new File("D:\\EnterTestClass.txt");
If (!file.exists()) {
Try {
file.createNewFile();
} Catch (IOException e) {
e.printStackTrace();
}
}
String jsonString = "{\"uid\":\"189024\", \"region\":\"SouthChina\", \"order\":29021.98}";
Gson gson = new Gson();
Map<String, String> retMap = gson.fromJson(jsonString,
New TypeToken<Map<String, String>>() {
}.getType());
String origin = retMap.get("uid").toString();
String destination = retMap.get("region").toString();
Write("[ uuid ] :" + LocalDateTime.now().toString() + "---" + origin + "---" + destination);
Return UUID.randomUUID().toString();
}
}
Discussion (1)0
Log in or sign up to continue

You can try referring the multiple jar files as list to  gateway.

Set AssemblyFileNameWithPath1="jar path 1" 

Set AssemblyFileNameWithPath2="jar path 2"
 Set gateway=##class(%Net.Remote.Gateway).%New()
 Set classpath=##class(%ListOfDataTypes).%New()
  Dclasspath.Insert(AssemblyFileNameWithPath1)

Dclasspath.Insert(AssemblyFileNameWithPath2)
 Set status=gateway.%Connect(Host,Port,NameSpace,10,classpath)