jbosswildflyjboss-modulesclassloading

How to specify that a JBoss WildFly deployment should load its lib module with services imported?


I have an ear file with a structure like this that I'm trying to deploy in WildFly 17:

my-application-ear.ear
|-- my-ejb-jar-1.jar
|-- my-ejb-jar-2.jar
|-- lib/
    |-- my-library-jar.jar
    |-- ...
|-- META-INF
    |-- MANIFEST.MF
    |-- jboss-deployment-structure.xml

my-library-jar contains content under META-INF/services that the standard classloader doesn't load by default.

I'm trying to use the services attribute to allow the classloader access to the META-INF/services directory, but I can't find a way to specify the library jar as a module, or as a resource that includes META-INF/services.

Is there a way to do this? This is an example of [some of the many] things I've tried:

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.3">
    <deployment>
        <dependencies>
            <!-- snip! -->
            ...

            <!-- These don't work - looking for a way to load lib jar files with services. -->
            <module name="my-library-jar.jar" services="import" />
            <module name="lib.my-library-jar.jar" services="import" />
            <module name="lib/my-library-jar.jar" services="import" />

            <module name="deployment.my-application-ear.ear.my-library-jar.jar" services="import" />
            <module name="deployment.my-application-ear.ear.lib.my-library-jar.jar" services="import" />
            <module name="deployment.my-application-ear.ear/my-library-jar.jar" services="import" />
            <module name="deployment.my-application-ear.ear/lib/my-library-jar.jar" services="import" />
            <module name="deployment.my-application-ear.ear.parent.my-library-jar.jar" services="import" />
        </dependencies>    
    </deployment>
</jboss-deployment-structure>

If possible I would prefer to use the deployment descriptor, rather than modify the manifest file's Dependencies attribute.

This application is quite large and worked well in JBoss 5.1, but its structure is proving hard to describe to the new classloader.


Solution

  • It turned out that I didn't need to do anything special to make the META-INF/services directories of jar files in the lib directory visible to the code in those same jar files.

    The answer was to replace all of the calls of this method:

    ServiceLocator.load(Class)
    

    ... with calls to the overloaded version of the method that takes a specific class loader:

    ServiceLocator.load(Class, ClassLoader)
    

    This JBossDeveloperForums reply provided the vital clue. The single argument calls worked flawlessly for ten years with JBossAS 5.1.0GA but didn't work with the more sophisticated class loading in WildFly 17.

    One small quirk of the two argument call is that if the service configurations are deployed as a module, then server-side proxy implementations deployed in the lib directory of the ear archive won't see them. I think this is because the proxy is loaded by the parent (lib) class loader and not an EJB module class loader that respects the declared dependencies in jboss-deployment-structure.xml. If the service configurations are also deployed in the lib directory the proxy can access them.