How to use kyotocabinet(JNI) in playframework?

1.6k views Asked by At

I'm tackling to use kyotocabinet in Playframework. and following error occurred.

I'm using Eclipse and playframework-1.2.3. and kyotocabinet is native library so I'm using its Java-Binding.

the reproduce code is simple. in controller:

public static void somePage() {
    DB db = new DB();//error occurred
    render();
}

Internal Server Error (500) for request GET /
Execution exception (In /app/controllers/TestApp.java around line 45)
NoClassDefFoundError occured : Could not initialize class kyotocabinet.DB

play.exceptions.JavaExecutionException: Could not initialize class kyotocabinet.DB
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:229)
    at Invocation.HTTP Request(Play!)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class kyotocabinet.DB
    at controllers.TestApp.somePage(TestApp.java:45)
    at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:546)

    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:500)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:476)

    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:471)

    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:159)
    ... 1 more

build in Eclipse was completed but error occured at runtime.

I guess it is because kyotocabinet.dll is missing.(only jkyotocabinet.jar was found) I configured the location of kyotocabinet.dll to Java Build Path > Source > Native Library Location of my playframework project. and it was good in other projects.

How to use native library in playframework? any example or tutorial?

Play.getFile and System.load didn't work.

package controllers;
import play.Play;
import play.jobs.*;

@OnApplicationStart
public class Bootstrap extends Job {
public void doJob() {
    String path = "D:/MyProject/lib/jkyotocabinet.dll";
    Play.getFile(path);
    //System.load(path); if this was enabled, following error occurred: "Native Library D:\MyProject\lib\jkyotocabinet.dll already loaded in another classloader". so I guess the dll was loaded.
    System.out.println("bootstrap loaded");//this is displayed.
}
}

UnsatisfiedLinkError occured : no jkyotocabinet in java.library.path

this Japanese blog tells Play!Framework cannot load native library. http://d.hatena.ne.jp/hjym_u/20110702/1309609277

I already tried these: Absolute path, Relative path, System.load, System.loadLibrary, Play.getFile.

as conclusive approach, I put jkyotocabinet.dll to current directory(D:/MyProejct/), and wrote this code.

public static void somePage(){
    File f = Play.getFile("jkyotocabinet.dll");
        if(f != null && f.isFile() && f.canRead() && f.canExecute()){//true
            DB db = new DB();//error occured. it reached here.
        }
    render();
}

Execution exception
NoClassDefFoundError occured : Could not initialize class kyotocabinet.DB

Play.getFile found the path "jkyotocabinet.dll" so jkyotocabinet.dll is in current directory so jvm should find it automatically.

anyone can use JNI in playframework?

finally, I could use kyotocabinet as PROD mode but not DEV mode.

Project/conf/application.conf

#application.mode=dev
application.mode=prod
2

There are 2 answers

0
emt14 On

Do as pere says but use the relative path from your application root. Not the absolute path. I.e. Play.getFile("lib\myfile.dll")

0
Pere Villega On

I assume you just need to load the dll into Java via System.load

If you place the ddl on your project, you may load it via Play.getFile inside your @OnApplicationStart controller. This should make it available to your application while the JVM is alive.

EDIT:

@KenichiYamamoto Play.getFile gets files from the application path. You are trying to use a full path in there.

Read this about loading the file in a container. It may be that (due to Play compile-reload system) you are hitting the "already loaded" error. Try to follow the example by adding the System.load inside a static block in your @OnApplicationStart