Usage of META-INF.services in module?

Hello,

I have a module which need to use META -INF.services.

A third party dependency need to load a class provided in the META -INF.services.

Is it possible ?

When the third party dependency try to load it, I have an exception.

I have ever tried something like this before the third party look for it.

 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  try{

    Thread.currentThread().setContextClassLoader(UtilsGst.class.getClassLoader());
    xxxxxxxxx

 } finally {
            Thread.currentThread().setContextClassLoader(classLoader);
 }

What's the Exception?

None of our modules use the ServiceLoader mechanism so I'm not able to tell you if there's something making this fundamentally impossible or not.

When the third party look for the class named in

com/bouyguesenergiesservices/ignition/common/videoviewer/
META-INF/org.freedesktop.gstreamer.glib.NativeObject$TypeProvider:

com.bouyguesenergiesservices.ignition.common.videoviewer.Types

it can't find it.
Stack trace:

java.lang.RuntimeException: java.lang.InstantiationException

at org.freedesktop.gstreamer.glib.NativeObject.objectFor(NativeObject.java:195)

at org.freedesktop.gstreamer.glib.Natives.objectFor(Natives.java:166)

at org.freedesktop.gstreamer.glib.Natives.callerOwnsReturn(Natives.java:140)

at org.freedesktop.gstreamer.lowlevel.GTypeMapper$2.fromNative(GTypeMapper.java:113)

at com.sun.jna.Function.invoke(Function.java:370)

at com.sun.jna.Library$Handler.invoke(Library.java:270)

at jdk.proxy3/jdk.proxy3.$Proxy123.g_value_dup_object(Unknown Source)

at org.freedesktop.gstreamer.glib.GObject.get(GObject.java:194)

...

at java.base/java.lang.Thread.run(Unknown Source)

Caused by: java.lang.InstantiationException: null

at java.base/jdk.internal.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(Unknown Source)

at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Unknown Source)

at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)

at org.freedesktop.gstreamer.glib.NativeObject.objectFor(NativeObject.java:187)

... 44 common frames omitted

I don't think your META-INF folder is in the correct location. It should be at the root of your JAR file.

1 Like

Old repo, but look at the structure here:

All of your modules provided jars should be on the same classloader, so I think this should fundamentally work.

seem to be ok ? or I need to put the META-INF.services at another location ???

It's not "META-INF.services", it's "META-INF/services". Two directories.

(not sure if that's what you have or it's just the IDE showing it that way)

Yes that IJ showing folder in that way

Do you have a no-arg constructor, explicit or implicit, in your service implementation class?

the service implementation class:

package org.freedesktop.gstreamer.examples;

import java.util.stream.Stream;
import org.freedesktop.gstreamer.glib.NativeObject;
import org.freedesktop.gstreamer.glib.Natives;

/**
 * Custom type registration for WebRTC example. This class is registered in
 * META-INF/services to be picked up by the {@link ServiceLoader}.
 */
public class Types implements NativeObject.TypeProvider {

    @Override
    public Stream<NativeObject.TypeRegistration<?>> types() {
        return Stream.of(
                Natives.registration(WebRTCICE.class, WebRTCICE.GTYPE_NAME, WebRTCICE::new)
        );
    }

}

Should the file actually be called org.freedesktop.gstreamer.glib.NativeObject.TypeProvider?

since TypeProvider is a static inner class?

I think I've have finally something which works, but I need to understand after multiples code changes.

  • Thread.currentThread().setContextClassLoader before the initial third-party lib init in the -common
  • Thread.currentThread().setContextClassLoader before the call of the function in the -gateway

both files added:

  • org.freedesktop.gstreamer.glib.NativeObject.TypeProvider
  • org.freedesktop.gstreamer.glib.NativeObject$TypeProvider

with reference to:

  • com.bouyguesenergiesservices.ignition.common.videoviewer.Types

I will see what it's necessary.