You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@netbeans.apache.org by Damian Carey <ja...@gmail.com> on 2019/08/17 06:12:10 UTC

Platform wrapped jar cannot access META-INF/service impl via ServiceLoader

Hi all,

We have a "mature" (10+ year old) Netbeans Platform Swing product, which
has 35+ modules. This all works well.

As usual, when one Netbeans module provides an Implementation we find it
from other Netbeans modules using the usual idiom ...
Provider: puts entry in META-INF/services
Consumer: MyClass myObj = Lookup.getDefault().lookup(MyClass.class);

Our current issue is that we need to add an external jar that is NOT built
using Netbeans, so it can't use Lookup. I have placed this external jar
into a module wrapper, and one of our modules depends on it so we can
successfully start this service as appropriate. Again, everything is
perfect with this setup.

The problem is that this external jar is looking for services from our
Netbeans platform product, it is seeking them using standard java
ServiceLoader capability, but the implementations are not found.

I *think* that if we use the Netbeans System ClassLoader then it CAN locate
the implementations, however we don't want to use the system classloader
because it will cause other issues.

Does anyone have any suggestions on how a wrapped jar might access Netbeans
META-INF/services implementations via vanilla Java ServiceLoader SPI
interface?

Any suggestions would be hugely appreciated.

Many thanks,
-Damian

Re: Platform wrapped jar cannot access META-INF/service impl via ServiceLoader

Posted by Damian Carey <ja...@gmail.com>.
Geertjan, Emi and Boris,
Many thanks for responding.
It seems that Lookup and ServiceLoader are similar, yet different enough to
be troublesome.
I will need to do more testing, but first I will try to inject the services
I need via a method, and not via META-INF/resources.
Much appreciated.
-Damian

On Sat, 17 Aug 2019 at 21:38, Boris Heithecker <bo...@gmx.net>
wrote:

> Are you sure that the services your third-party jar wants to look up via
> java.util.ServiceLoader.load(Clazz.class) are registered as
> META-INF/services entries?
> The problem could be that Lookup.getDefault().lookup(Clazz.class) also
> looks up services registered in the system file system (layer.xml) in the
> /Services subdirectory.
> Also, are you sure that your third-party jar does not specify a particular
> class loader it finds appropriate when looking up up the service, i.e.
> using the method signature java.util.ServiceLoader.load(Clazz.class,
> MyLoader.class)? In the default case,
> java.util.ServiceLoader.load(Clazz.class) uses
> Thread.currentThread().getContextClassLoader() to look up the required
> service, but this may be jdk implementation dependent.
> Does your external jar require the service at an early phase during
> start-up? The implementing module may not be fully ready yet.
> Also, make sure no attempt is made to double load the service interface
> class from two different classloaders. The NetBeans classloader system
> allows, in principle, multiple definitions of the same class with the same
> qualified name. But these are not available on the context classloader.
> Look through the logs, you get it warning saying something like ".. won't
> arbitrarily load class x from class loader y and z".
> Maybe this helps.
> Boris
>
>
> On Sat, 17 Aug 2019 at 08:12, Damian Carey <ja...@gmail.com> wrote:
>
>> Hi all,
>>
>> We have a "mature" (10+ year old) Netbeans Platform Swing product, which
>> has 35+ modules. This all works well.
>>
>> As usual, when one Netbeans module provides an Implementation we find it
>> from other Netbeans modules using the usual idiom ...
>> Provider: puts entry in META-INF/services
>> Consumer: MyClass myObj = Lookup.getDefault().lookup(MyClass.class);
>>
>> Our current issue is that we need to add an external jar that is NOT
>> built using Netbeans, so it can't use Lookup. I have placed this external
>> jar into a module wrapper, and one of our modules depends on it so we can
>> successfully start this service as appropriate. Again, everything is
>> perfect with this setup.
>>
>> The problem is that this external jar is looking for services from our
>> Netbeans platform product, it is seeking them using standard java
>> ServiceLoader capability, but the implementations are not found.
>>
>> I *think* that if we use the Netbeans System ClassLoader then it CAN
>> locate the implementations, however we don't want to use the system
>> classloader because it will cause other issues.
>>
>> Does anyone have any suggestions on how a wrapped jar might access
>> Netbeans META-INF/services implementations via vanilla Java ServiceLoader
>> SPI interface?
>>
>> Any suggestions would be hugely appreciated.
>>
>> Many thanks,
>> -Damian
>>
>
>
> --
> Boris Heithecker
>
>
> Dr. Boris Heithecker
> Lüneburger Str. 30
> 28870 Ottersberg
> Festnetz: +49 4205 315834
> Mobil: +49 170 6137015
>

Re: Platform wrapped jar cannot access META-INF/service impl via ServiceLoader

Posted by Boris Heithecker <bo...@gmx.net>.
Are you sure that the services your third-party jar wants to look up via
java.util.ServiceLoader.load(Clazz.class) are registered as
META-INF/services entries?
The problem could be that Lookup.getDefault().lookup(Clazz.class) also
looks up services registered in the system file system (layer.xml) in the
/Services subdirectory.
Also, are you sure that your third-party jar does not specify a particular
class loader it finds appropriate when looking up up the service, i.e.
using the method signature java.util.ServiceLoader.load(Clazz.class,
MyLoader.class)? In the default case,
java.util.ServiceLoader.load(Clazz.class) uses
Thread.currentThread().getContextClassLoader() to look up the required
service, but this may be jdk implementation dependent.
Does your external jar require the service at an early phase during
start-up? The implementing module may not be fully ready yet.
Also, make sure no attempt is made to double load the service interface
class from two different classloaders. The NetBeans classloader system
allows, in principle, multiple definitions of the same class with the same
qualified name. But these are not available on the context classloader.
Look through the logs, you get it warning saying something like ".. won't
arbitrarily load class x from class loader y and z".
Maybe this helps.
Boris


On Sat, 17 Aug 2019 at 08:12, Damian Carey <ja...@gmail.com> wrote:

> Hi all,
>
> We have a "mature" (10+ year old) Netbeans Platform Swing product, which
> has 35+ modules. This all works well.
>
> As usual, when one Netbeans module provides an Implementation we find it
> from other Netbeans modules using the usual idiom ...
> Provider: puts entry in META-INF/services
> Consumer: MyClass myObj = Lookup.getDefault().lookup(MyClass.class);
>
> Our current issue is that we need to add an external jar that is NOT built
> using Netbeans, so it can't use Lookup. I have placed this external jar
> into a module wrapper, and one of our modules depends on it so we can
> successfully start this service as appropriate. Again, everything is
> perfect with this setup.
>
> The problem is that this external jar is looking for services from our
> Netbeans platform product, it is seeking them using standard java
> ServiceLoader capability, but the implementations are not found.
>
> I *think* that if we use the Netbeans System ClassLoader then it CAN
> locate the implementations, however we don't want to use the system
> classloader because it will cause other issues.
>
> Does anyone have any suggestions on how a wrapped jar might access
> Netbeans META-INF/services implementations via vanilla Java ServiceLoader
> SPI interface?
>
> Any suggestions would be hugely appreciated.
>
> Many thanks,
> -Damian
>


-- 
Boris Heithecker


Dr. Boris Heithecker
Lüneburger Str. 30
28870 Ottersberg
Festnetz: +49 4205 315834
Mobil: +49 170 6137015

Re: Platform wrapped jar cannot access META-INF/service impl via ServiceLoader

Posted by Geertjan Wielenga <ge...@apache.org>.
I can't respond theoretically to this but would be happy to look at it if
you could put a small app together that reproduces this, on GitHub.

Gj

On Sat, Aug 17, 2019 at 8:12 AM Damian Carey <ja...@gmail.com> wrote:

> Hi all,
>
> We have a "mature" (10+ year old) Netbeans Platform Swing product, which
> has 35+ modules. This all works well.
>
> As usual, when one Netbeans module provides an Implementation we find it
> from other Netbeans modules using the usual idiom ...
> Provider: puts entry in META-INF/services
> Consumer: MyClass myObj = Lookup.getDefault().lookup(MyClass.class);
>
> Our current issue is that we need to add an external jar that is NOT built
> using Netbeans, so it can't use Lookup. I have placed this external jar
> into a module wrapper, and one of our modules depends on it so we can
> successfully start this service as appropriate. Again, everything is
> perfect with this setup.
>
> The problem is that this external jar is looking for services from our
> Netbeans platform product, it is seeking them using standard java
> ServiceLoader capability, but the implementations are not found.
>
> I *think* that if we use the Netbeans System ClassLoader then it CAN
> locate the implementations, however we don't want to use the system
> classloader because it will cause other issues.
>
> Does anyone have any suggestions on how a wrapped jar might access
> Netbeans META-INF/services implementations via vanilla Java ServiceLoader
> SPI interface?
>
> Any suggestions would be hugely appreciated.
>
> Many thanks,
> -Damian
>

Re: Platform wrapped jar cannot access META-INF/service impl via ServiceLoader

Posted by Emilian Bold <em...@gmail.com>.
I don't have a solution at hand but remember that the lookup will keep
a single object instance in memory for a given service entry while the
ServiceLoader will create fresh instances if it's just reading
META-INF/service files (unless the JAR keeps a reference to a single
ServiceLoader instance so the cache is reused).

So you want a "bridge" from ServiceLoader to the default lookup or
just a way to instantiate the services?

I guess the most heavy duty solution would be to bytecode engineer the
3rd party JAR so you it either calls the lookup or allows you to
inject values.

PS: I had the reverse problem: the ServiceLoader finding classes when
I didn't want it to find any (geotools JARs). This was happening
because those JARs were in the boot classpath for some reason.

--emi

On Sat, Aug 17, 2019 at 9:12 AM Damian Carey <ja...@gmail.com> wrote:
>
> Hi all,
>
> We have a "mature" (10+ year old) Netbeans Platform Swing product, which has 35+ modules. This all works well.
>
> As usual, when one Netbeans module provides an Implementation we find it from other Netbeans modules using the usual idiom ...
> Provider: puts entry in META-INF/services
> Consumer: MyClass myObj = Lookup.getDefault().lookup(MyClass.class);
>
> Our current issue is that we need to add an external jar that is NOT built using Netbeans, so it can't use Lookup. I have placed this external jar into a module wrapper, and one of our modules depends on it so we can successfully start this service as appropriate. Again, everything is perfect with this setup.
>
> The problem is that this external jar is looking for services from our Netbeans platform product, it is seeking them using standard java ServiceLoader capability, but the implementations are not found.
>
> I *think* that if we use the Netbeans System ClassLoader then it CAN locate the implementations, however we don't want to use the system classloader because it will cause other issues.
>
> Does anyone have any suggestions on how a wrapped jar might access Netbeans META-INF/services implementations via vanilla Java ServiceLoader SPI interface?
>
> Any suggestions would be hugely appreciated.
>
> Many thanks,
> -Damian

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@netbeans.apache.org
For additional commands, e-mail: users-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists