views:

109

answers:

3

Hi,

I have troubles using the java ServiceLoader in a NetBeans module application. Here is what I'm trying to do (and it works in a normal java application in Eclipse):

I have an interface.jar, which declares the interface. And I have implementations.jar, which has several implementations of this interface, all specified in the spi/META-INF/services/my.package.name.MyInteface file (this file is in the implemenations.jar).

I also have a class ImplementationHandler (in yet another handler.jar), which has the following method to load all implementations:

private static List<MyInterface<?>> loadAllImplementations() {
    List<MyInterface<?>> foundImplementations = Lists.newArrayList();
    try {
        for (MyInterface implementation : ServiceLoader.load(MyInterface.class)) {
            foundImplementations.add(implementation);
        }
    } catch (ServiceConfigurationError error) {
        system.out.println("Exception happened");
    }
    return foundImplementations;
}

This code returns all implementations in Eclipse normal application (the foundImplementations.size() > 0).

However under NetBeans, it can't find anything (foundImplementations.size() == 0).

More details:
I have the source of a NetBeans module application (open source, not written by me), which I need to extend by using some of MyInterface implementations. The interface.jar, implementations.jar and the handler.jar are created in Eclipse and they are part of another application.

In the NetBeans, I opened the module which needs to use the new impplementations and I added all my 3 jars as external libraries (NetBeans copied them into its ext folder, which I don't want but I can't do anything about - I want them in another myext folder, but that's another story). Then I rebuilt everything and tried to use one of my implementations, but it was not found... The code that gets an implementation is in the ImplementationHandler class and looks like:

public static final <T> MyInteface<T> getByName(String name) {
    for (MyInteface implementation : loadAllImplementations()) {
        if (implementation.getName().equals(name)) {
            return implementation;
        }
    }

    throw new IllegalArgumentException("Unable to find MyInterface class for: " + name);
}

I got my exception "Unable to find MyInteface class for: myImplementationName"...

My knowledge about NetBeans is very limited and I was wondering is there something more that I need to do in order to get this working?

A: 

The ServiceLoader.load(Class) uses the current thread's context class loader to load all the implementations. It may be that in your case your implementation classes in your jar file (implementation.jar) are not in that class loader's classpath.

You may have to try different approaches for this :

  • You may either need to have all the jars in the netbeans module's classpath or,
  • You may need to create a class loader (probably a URLClassLoader having those jars in its classpath) and use the ServiceLoader.load(Class, ClassLoader) and pass a that classloader.
  • There is another option you could try but I am not sure about this: The jar file spec allows you to specify Class-Path manifest attribute, to which you can add 'implementation.jar' entry. More details here

Most likely, the handler.jar and implementations.jar are not loaded by the same class loader. Also you may want to take a look as to why your files are getting to ext folder.

Hope this helps.

Edit:

  • Also try calling the ServiceLoader.load(Class, null) which uses the System class loader (the one that started the application). Probably that classloader may be able to find classes in jars located in the ext directory.
naikus
Hi, thanks for the answer! I'm going to try the System class loader first. The jars should be in the netbeans module classpath, since I'm adding them as libraries to the module which will use them and not to the whole project. I think it is by default that your jars then go in the ext folder and I don't think this matters so much, since the netbeans generates this Class-Path manifest attribute automatcally, which you described. I checked this attribute and it correctly points to all jars in the ext folder, and the jars are there.
m_pGladiator
system class loader does not see them either :(
m_pGladiator
May be @Jörn Horstmann's comment may have some clue? about the spi directory? Is the META-INF directory at the root of the jar?The last resort is trying the URLClassLoader approach.
naikus
yes, it is in the root. The URLClasLoader approach is really the last resort maybe... I'll try it tommorow
m_pGladiator
I found out that this module uses some custom class loaders in the code, with magical methods inside like "resolveHiddenClasspath"... I guess I should look deeply in the source of that moudle to have a clue what is going on
m_pGladiator
A: 

I gave up, and replaced ClassLoader with JSPF. This works out of the box and I don't need to know about the internals of a third party program, written as NetBeans module and how this affects the classpath given to the class loaders.

m_pGladiator
A: 

how to execute ireport in netbeans it menas i want to know the code for execuation i have swing application and i plugin ireport but which code i have to wirte on button action event for execute a code.

Amit