javaplayframeworkplayframework-2.0olap4j

Play Framework 2.1.0 - NoClassDefFoundError when registering JDBC driver using Class.forName


I am trying to use olap4j with Play 2.1.0 but am having great difficulty in getting some olap4j code to work in a Play controller, this same code works just fine in a separate Eclipse Java project, hence I have ruled out any issues with olap4j or my XMLA server it connects to. I have added the olap4j JAR files as unmanaged dependencies by placing the JAR files in \lib folder. I am running in Play DEV mode.

The following code returns the exception below:

Java Code:

Class.forName("org.olap4j.driver.xmla.XmlaOlap4jDriver");

Error:

[RuntimeException: java.lang.NoClassDefFoundError: edu/emory/mathcs/backport/java/util/concurrent/Callable] 

After some further digging around I found that Play uses it's own Classloader, so I tried the following:

Java Code:

Play.application().classloader().loadClass("org.olap4j.driver.xmla.XmlaOlap4jDriver");

This seems to eliminate the NoClassDefFoundError error, however the following exception is raised:

Error:

java.sql.SQLException: No suitable driver found for jdbc:xmla:Server=http://localhost/OLAP/msmdpump.dll

Perhaps I need to add the JDBC class registration in a Global class? Any help would be much appreciated. The JavaDocs for org.olap4j.driver.xmla.XmlaOlap4jDriver says the following, which is exactly what I am following:

Since olap4j is a superset of JDBC, you register this driver as you would any JDBC driver: Class.forName("org.olap4j.driver.xmla.XmlaOlap4jDriver"); Then create a connection using a URL with the prefix "jdbc:xmla:".

Full Code:

package controllers;

import play.Play;
import play.mvc.*;
import org.olap4j.*;
import org.olap4j.metadata.Member;
import java.sql.*;

public class Test extends Controller {

public static Result index() {

    String server = "http://localhost/OLAP/msmdpump.dll";
    String user = "user";
    String password = "password";
    String result = "0";

    try {
        //Class.forName("org.olap4j.driver.xmla.XmlaOlap4jDriver");
        Play.application().classloader().loadClass("org.olap4j.driver.xmla.XmlaOlap4jDriver");
        try {
            Connection connection = DriverManager.getConnection("jdbc:xmla:Server="+server, user, password);
        } catch (SQLException e) {
            result = e.getMessage();
        }
    } catch (ClassNotFoundException e) {
        result = e.getMessage();
    }

    return ok(result);
}
}

Solution

  • According to this thread, your first approach should work just fine, e.g. this:

    Class.forName("org.olap4j.driver.xmla.XmlaOlap4jDriver");
    

    The error you're getting,

    java.lang.NoClassDefFoundError: edu/emory/mathcs/backport/java/util/concurrent/Callable
    

    implies that you need to add backport-util-concurrent.jar also to your class path (like mentioned in this thread). I guess it should work after that. That jar is Backport Concurrent Util jar, available on its site. Place that also into your lib folder.