Problems with dependencies when service loading a fat jar in java

86 Views Asked by At

I have a problem where if I try to service load a fat jar built with maven shade plugin, my java service loader cannot find all dependencies inside the fat jar. I can see all the dependencies inside the jar file if I extract it and I can even run the main class file either through IntelliJ or by using java -jar auth-plugin-jar-with-dependencies.jar inside the terminal and I do not get any problems with dependencies then.

However if i service load the jar it does not find the correct dependencies and when I for an example componentScan the dependencies with Spring (not using springboot just spring) it will not find the correct dependencies. This will also happen with for an example Jakarta.

This is how i package my jar:

    <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <finalName>auth-plugin-jar-with-dependencies</finalName>
                            <transformers>
                                <transformer implementation=
                                                           "org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>test</mainClass>
                                    <manifestEntries>
                                        <addClasspath>true</addClasspath>
                                        <Multi-Release>true</Multi-Release>
                                    </manifestEntries>
                                </transformer>
                            </transformers>
                            <createDependencyReducedPom>false</createDependencyReducedPom>
                            <filters>
                                <filter>
                                    <artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>module-info.class</exclude>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                            <artifactSet>
                                <excludes>
                                    <exclude>
                                        jakarta.activation:jakarta.activation-api
                                    </exclude>
                                    <exclude>
                                        jakarta.xml.ws:jakarta.xml.ws-api
                                    </exclude>
                                </excludes>
                            </artifactSet>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

This is how I load my jar:

    public static List<AuthPlugin> loadPlugins(Class<AuthPlugin> pluginClazz) {
        ClassLoader baseClassLoader = pluginClazz.getClassLoader();

        // Assuming the JAR file is in the /target directory
        File targetDirectory = new File("../auth/target");
        File pluginJarFile = new File(targetDirectory, "auth-plugin-jar-with-          
dependencies.jar");
        System.err.println(targetDirectory.getPath()+ "         " + pluginJarFile.getPath());

        try {
            URL jarUrl = pluginJarFile.toURI().toURL();
            URLClassLoader jarClassLoader = new URLClassLoader(new URL[]{jarUrl}, baseClassLoader);

            ServiceLoader<AuthPlugin> serviceLoader = ServiceLoader.load(pluginClazz, jarClassLoader);
            serviceLoader.reload();



            return serviceLoader.stream()
                    .map(ServiceLoader.Provider::get)
                    .collect(Collectors.toList());
        } catch (MalformedURLException e) {
            // Handle exception appropriately
            e.printStackTrace();
            return null;
        }
    }

This is how I component scan

@Configuration
@ComponentScan(
        basePackages = [
                "se.plugin.auth",
                "se.example.lib.common.config",
                "se.example.lib.common.soap",
                "se.example.lib.common.http"

        ],
        nameGenerator = PackageBeanNameGenerator
)
class PluginConfiguration {
    private static final Logger logger = LogManager.getLogger()

    PluginConfiguration() {
        logger.error("Initializing PluginConfiguration")
    }


}

This is how I grab the bean

        GetAuthorizationService getAuthorizationService = context.getBean(GetAuthorizationService.class);


And then I get this error

Message: No qualifying bean of type 'se.plugin.auth.integration.example.authservice.GetAuthorizationService' available

If I were to declare it, and all needed spring under components as a bean instead like this:


    @Bean
    GetAuthorizationService getAuthorizationService() {
        return new GetAuthorizationService()
        // Configure the bean as needed
    }

They would manage to load in, but I would then get this:

Message: Implementation of Jakarta XML Binding-API has not been found on module path or classpath. Stacktrace: [jakarta.xml.bind.ContextFinder.newInstance(ContextFinder.java:147), jakarta.xml.bind.ContextFinder.find(ContextFinder.java:341)

One way to actually load my simulator would be to do this: java -cp simulator.jar;auth-plugin-with-dependencies.jar Main

And then it would work perfectly fine, but not if i were to just run java -jar simulator.jar

0

There are 0 best solutions below