Question

I'm currently trying to load and use the Gephi Toolkit from within a .Net 4 C# website.

I have a version of the toolkit jar file compiled against the IKVM virtual machine, which works as expected from a command line application using the following code:

var controller = (ProjectController)Lookup.getDefault().lookup(typeof(ProjectController));
controller.closeCurrentProject();
controller.newProject();
var project = controller.getCurrentProject();
var workspace = controller.getCurrentWorkspace();

The three instances are correctly instantiated in a form similar to org.gephi.project.impl.ProjectControllerImpl@8ddb93.

If however I run the exact same code, with the exact same using statements & references, the very first line loading the ProjectController instance returns null.

I have tried a couple of solutions

Firstly, I have tried ignoring the Lookup.getDefault().lookup(type) call, instead trying to create my own instances:

var controller = new ProjectControllerImpl();
controller.closeCurrentProject();
controller.newProject();
var project = controller.getCurrentProject();
var workspace = controller.getCurrentWorkspace();

This fails at the line controller.newProject();, I think because internally (using reflector) the same Lookup.getDefault().lookup(type) is used in a constructor, returns null and then throws an exception.

Secondly, from here: Lookup in Jython (and Gephi) I have tried to set the %CLASSPATH% to the location of both the toolkit JAR and DLL files.

Is there a reason why the Lookup.getDefault().lookup(type) would not work in a web environment? I'm not a Java developer, so I am a bit out of my depth with the Java side of this.

I would have thought it possible to create all of the instances myself, but haven't been able to find a way to do so.

I also cannot find a way of seeing why the ProjectController load returned null. No exception is thrown, and unless I'm being very dumb, there doesn't appear to be a method to see the result of the attempted load.

Update - Answer

Based on the answer from Jeroen Frijters, I resolved the issue like this:

public class Global : System.Web.HttpApplication
{
    public Global()
    {
        var assembly = Assembly.LoadFrom(Path.Combine(root, "gephi-toolkit.dll"));
        var acl = new AssemblyClassLoader(assembly);
        java.lang.Thread.currentThread().setContextClassLoader(new MySystemClassLoader(acl));
    }
}

internal class MySystemClassLoader : ClassLoader
{
    public MySystemClassLoader(ClassLoader parent)
        : base(new AppDomainAssemblyClassLoader(typeof(MySystemClassLoader).Assembly))
    { }
}

The code ikvm.runtime.Startup.addBootClassPathAssemby() didn't seem to work for me, but from the provided link, I was able to find a solution that seems to work in all instances.

Was it helpful?

Solution

This is a Java class loader issue. In a command line app your main executable functions as the system class loader and knows how to load assembly dependencies, but in a web process there is no main executable so that system class loader doesn't know how to load anything useful.

One of the solutions is to call ikvm.runtime.Startup.addBootClassPathAssemby() to add the relevant assemblies to the boot class loader.

For more on IKVM class loading issues see http://sourceforge.net/apps/mediawiki/ikvm/index.php?title=ClassLoader

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top