How to load native library to play framework?

fail to load a native library using activator (Play Framework)

  • I'm trying to load a native library in my Play 2.4.x application. I have written a simple test that works fine both in the IDE (IntelliJ) and in SBT. In both case I'm setting the java.library.path to get the tests to run. In the IDE, I set -Djava.library.path=$USER_HOME$/dev/lindoapi/bin/linux64 in the test run configuration. As per the sbt documentation, my build.sbt is forking the JVM and setting the java.library.path. javaOptions += "-Djava.library.path=/home/aczerwon/dev/lindoapi/bin/linux64" fork := true The following test passes just fine in both the IDE and from activator test. class LindoApiSpec extends Specification { System.loadLibrary("lindojni") "The Lindo API" should { "have a valid license" in { val lindo = new LindoEnvironment() lindo.apiVerion() must beSuccessfulTry.withValue("LINDO API Version 9.0.2120.225") } } When outside of the testing context, I load the native library in Play's startup lifecycle. object Global extends GlobalSettings { override def beforeStart(app: Application) = { System.loadLibrary("lindojni") } } When I call that same method from the webapi (activator ~run), I'm getting an UnsatisfiedLinkError error. 1) Error injecting constructor, java.lang.UnsatisfiedLinkError: no lindojni in java.library.path at play.api.GlobalPlugin.<init>(GlobalSettings.scala:262) at play.api.GlobalPlugin.class(GlobalSettings.scala:262) while locating play.api.GlobalPlugin The web api looks like this: class OptimizationApi extends Controller { def version() = Action { val lindo = new LindoEnvironment() lindo.apiVerion() match { case Success(version) => Ok(version) case Failure(e) => BadRequest(e.getMessage) } } } I assumed that my build.sbt would fork the JVM and set the java.library.path for both test and run contexts. Any clues as to what I'm doing wrong? New Information When I start activator -Djava.library.path=$USER_HOME$/dev/lindoapi/bin/linux64 or set JAVA_OPTS, the call to System.loadLibrary(...) in the startup lifecycle passes. I still get the UnsatisfiedLinkError, but it happens later when I make a call to the native library via JNI. Very strange.

  • Answer:

    I found a solution to the issue https://github.com/playframework/playframework/issues/2212#issuecomment-82024667. The native library and its java counterpart must be in the same class loader. Create a class similar to: public final class PlayNativeLibraryLoader { public static void load(String library) { System.load(library); } } And now you can use it in the Play startup lifecycle. object Global extends GlobalSettings { override def beforeStart(app: Application) = { PlayNativeLibraryLoader.load(app.getFile("./lib/lindoapi/linux64/liblindojni.so").getPath) Logger.info("Lindo native library loaded") } }

andyczerwonka at Stack Overflow Visit the source

Was this solution helpful to you?

Just Added Q & A:

Find solution

For every problem there is a solution! Proved by Solucija.

  • Got an issue and looking for advice?

  • Ask Solucija to search every corner of the Web for help.

  • Get workable solutions and helpful tips in a moment.

Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.