spring-projects-experimental / spring-boot-thin-launcher

Tools for building "thin" executable jars, with a focus on, but not exclusively for, Spring Boot
https://github.com/dsyer/spring-boot-thin-launcher
Apache License 2.0
684 stars 90 forks source link

Use ThinLauncher as a dependency #173

Open JamesPeters98 opened 3 years ago

JamesPeters98 commented 3 years ago

Is it possible to use a Spring Boot project using the Thin Launcher as a dependency on another project?

I.e It would be useful if the Maven plugin generated a class that can be called to load all the dependencies into the ClassLoader of the dependant project.

Currently this doesn't seem possible, I have tried using reflection to start the ThinJarWrapper but that results in the ThinJarLauncher not being able to find the Main class:

        try {
            var clazz = Class.forName("org.springframework.boot.loader.wrapper.ThinJarWrapper");
            var method = clazz.getMethod("main", String[].class);
            method.invoke(null, (Object) new String[]{});
        } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
        }
18:27:54] [Server thread/WARN]: Caused by: java.lang.IllegalStateException: Cannot locate main class in jar:file:/C:/Users/James/Documents/GitHub/ChestsPlusPlus/Server/plugins/ChestsPlusPlus-2.5-Beta.jar!/
[18:27:54] [Server thread/WARN]:    at org.springframework.boot.loader.thin.ArchiveUtils.findMainClass(ArchiveUtils.java:98)
[18:27:54] [Server thread/WARN]:    at org.springframework.boot.loader.thin.ThinJarLauncher.getMainClass(ThinJarLauncher.java:347)
[18:27:54] [Server thread/WARN]:    at org.springframework.boot.loader.Launcher.launch(Launcher.java:57)
[18:27:54] [Server thread/WARN]:    at org.springframework.boot.loader.thin.ThinJarLauncher.launch(ThinJarLauncher.java:195)
[18:27:54] [Server thread/WARN]:    at org.springframework.boot.loader.thin.ThinJarLauncher.main(ThinJarLauncher.java:141)
[18:27:54] [Server thread/WARN]:    ... 28 more
[18:27:54] [Server thread/WARN]: Caused by: java.lang.IllegalStateException: Unable to find a single main class from the following candidates [com.jamesdpeters.chestsplusplusdatabase.ChestsPlusPlusDatabaseApplication, com.jamesdpeters.minecraft.chests.lang.LangFileProperties, org.springframework.boot.loader.wrapper.ThinJarWrapper]
[18:27:54] [Server thread/WARN]:    at org.springframework.boot.loader.tools.MainClassFinder$SingleMainClassCallback.getMainClassName(MainClassFinder.java:432)
[18:27:54] [Server thread/WARN]:    at org.springframework.boot.loader.tools.MainClassFinder$SingleMainClassCallback.access$100(MainClassFinder.java:403)
[18:27:54] [Server thread/WARN]:    at org.springframework.boot.loader.tools.MainClassFinder.findSingleMainClass(MainClassFinder.java:198)
[18:27:54] [Server thread/WARN]:    at org.springframework.boot.loader.tools.MainClassFinder.findSingleMainClass(MainClassFinder.java:180)
[18:27:54] [Server thread/WARN]:    at org.springframework.boot.loader.thin.ArchiveUtils.findMainClass(ArchiveUtils.java:94)
[18:27:54] [Server thread/WARN]:    ... 32 more

The ideal situation would be to be able to call a class that would load everything into the classpath without actually launching the main method of the Spring Boot application - since that can now be handled by the dependant project.

dsyer commented 2 years ago

I'm not 100% sure what the use case is, but I have used the thin launcher as a dependency so I know it is possible. There are some open issues about making it easier (e.g. #92, #43).

cforce commented 2 years ago

Is the launcher still useful/relevant for a spring cloud function project which already runs with spring boot 3.x ? Is the launcher getting part of spring boot 3.x? What is the difference compared to using maven-shade-plugin ?

<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>${maven.shade.plugin.version}</version>
                <configuration>
                    <createDependencyReducedPom>false</createDependencyReducedPom>
                    <finalName>demo</finalName>
                    <filters>
                        <filter>
                            <artifact>*:*</artifact>
                            <excludes>
                                <!-- Suppress module-info.class warning -->
                                <exclude>module-info.class</exclude>
                            </excludes>
                        </filter>
                    </filters>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
dsyer commented 2 years ago

I'm not sure that question is relevant to this issue.

cforce commented 2 years ago

Yes, its not ideal here :-). I created issues more on the topic "spring cloud function" https://github.com/spring-cloud/spring-cloud-function/issues/938