Search code examples
javadllserial-portexecutable-jarrxtx

How to make a executable jar file with .dll - RXTX


My programm shall communicate via RS232, therefore i use a .jar and two .dll's from RXTX. At the end I want to run it from a single .jar file.

To solve this problem i used this tutorial. But if I run the program from Eclipse (or after exporting from console) I get this exception:

java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path thrown while loading gnu.io.RXTXCommDriver Exception in thread "main" java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path

Here is an minimal example of my code

private static final String LIB = "lib/";
private final static String RXTXPARALLEL = "rxtxParallel";
private final static String RXTXSERIAL = "rxtxSerial";

static {
    try {
        System.loadLibrary(RXTXSERIAL);
        System.loadLibrary(RXTXPARALLEL);
        } catch (UnsatisfiedLinkError e) {
            loadFromJar();
        }
    }

public static void main(String[] args) {
    //RS232 is this class
    RS232 main = new RS232();
    main.connect("COM15");

}

private static void loadFromJar() {
    String path = "AC_" + new Date().getTime();
    loadLib(path, RXTXPARALLEL);
    loadLib(path, RXTXSERIAL);
}


private static void loadLib(String path, String name) {
    name = name + ".dll";
    try {
        InputStream in = ResourceLoader.load(LIB + name);
        File fileOut = new File(System.getProperty("java.io.tmpdir") + "/"
            + path + LIB + name);

        OutputStream out = FileUtils.openOutputStream(fileOut);
        IOUtils.copy(in, out);
        in.close();
        out.close();
        System.load(fileOut.getAbsolutePath());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private void connect(String portName) {

    CommPortIdentifier portIdentifier;
    try {
        //Here the exception is thrown
        portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
    } catch (NoSuchPortException exc) {
        exc.printStackTrace();
        return;
    }
  //... some other code
}

Is there a way to get an executable .jar file?


Solution

  • You have a few options. Try to copy the .dll files in the runtime folder and override the files at each start of your program. A second option is to copy the files in a fix folder and add the path of the folder to the environment variables in MS Windows. You can also override the files at each start.

    Another possibility is to add the temporary folder to the MS Windows environment variables at runntime. But be careful with this solution, for more information read this post.

    static {
        try {
            System.loadLibrary(RXTXSERIAL);
            System.loadLibrary(RXTXPARALLEL);
        } catch (UnsatisfiedLinkError exc) {
            initLibStructure();
        }
    }
    
    
    private static void initLibStructure() {
    
        try {
            //runntime Path
            String runPath = new File(".").getCanonicalPath();
    
            //create folder
            File dir = new File(runPath + "/" + LIB);
            dir.mkdir();
    
            //get environment variables and add the path of the 'lib' folder
            String currentLibPath = System.getProperty("java.library.path");
            System.setProperty("java.library.path",
                    currentLibPath + ";" + dir.getAbsolutePath());
    
            Field fieldSysPath = ClassLoader.class
                    .getDeclaredField("sys_paths");
            fieldSysPath.setAccessible(true);
            fieldSysPath.set(null, null);
    
            loadLib(runPath, RXTXPARALLEL);
            loadLib(runPath, RXTXSERIAL);
    
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private static void loadLib(String path, String name) {
        name = name + ".dll";
        try {
            InputStream in = ResourceLoader.load(LIB + name);
            File fileOut = new File(path + "/" + LIB + name);
    
            OutputStream out = FileUtils.openOutputStream(fileOut);
            IOUtils.copy(in, out);
            in.close();
            out.close();
            System.load(fileOut.getAbsolutePath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }