Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I start a Spring Boot WAR with PropertiesLauncher?

Tags:

spring-boot

I have a Spring Boot 1.2 app packaged as a WAR because I need to be able to deploy the app in an app server.

I also want to configure an external path which will contain jars to be added to the classpath. After reading the Launcher documentation, I configured the build to use PropertiesLauncher to this end :

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <configuration>
    ...
    <layout>ZIP</layout>
  </configuration>
</plugin>

I tried to start the app with various combinations of this additional system property : -Dloader.path=lib/,lib-provided/,WEB-INF/classes,<my additional path>

But I always end up with this error :

java.lang.IllegalArgumentException: Invalid source folder C:\<path to my war>\<my war>.war
    at org.springframework.boot.loader.archive.ExplodedArchive.<init> ExplodedArchive.java:78)
    at org.springframework.boot.loader.archive.ExplodedArchive.<init>(ExplodedArchive.java:66)
    at org.springframework.boot.loader.PropertiesLauncher.addParentClassLoaderEntries(PropertiesLauncher.java:530)
    at org.springframework.boot.loader.PropertiesLauncher.getClassPathArchives(PropertiesLauncher.java:451)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:60)
    at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:609)

I looked at the source code and it seems that PropertiesLauncher can only handle jar archives (ending with ".jar" or ".zip") and "exploded archives" (not ending with the former)

Is it possible to do achieve what I want ? Am I doing it wrong ?

If it's not possible, which alternative is there ?

like image 586
gregfqt Avatar asked Nov 27 '15 11:11

gregfqt


2 Answers

If somebody end up here this might be useful:

java -cp yourSpringBootWebApp.war -Dloader.path=yourSpringBootWebApp.war!/WEB-INF/classes/,yourSpringBootWebApp.war!/WEB-INF/,externalLib.jar org.springframework.boot.loader.PropertiesLauncher

(Spring-Boot 1.5.9)

https://docs.spring.io/spring-boot/docs/1.5.x/reference/html/executable-jar.html#executable-jar-launching

like image 58
ivsud Avatar answered Sep 30 '22 19:09

ivsud


In Spring Boot 1.2, PropertiesLauncher handles .jar and .zip files as "jar archives" and everything else as "exploded archives" (unzipped jars). It does not properly handles .war

Here's the alternative I found :

I eventually switched back to the regular war launcher and I managed to configure a folder which jar contents are added to the classpath using a SpringApplicationRunListener such as this (pseudo-code for concision) :

public class ClasspathExtender implements SpringApplicationRunListener {

    public void contextPrepared(ConfigurableApplicationContext context) {

        // read jars folder path from environment
        String path = context.getEnvironment().getProperty("my.jars-folder");

        // enumerate jars in the folder
        File[] files = new File(path).listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) { return name.endsWith(".jar"); }
        });

        URL[] urls = // convert files array to urls array

        // create a new classloader which contains the jars...   
        ClassLoader extendedClassloader = new URLClassLoader(urls, context.getClassLoader());

        // and replace the context's classloader
        ((DefaultResourceLoader) context).setClassLoader(extendedClassloader);
    }

    // other methods are empty
}

This listener is instanciated by declaring it in a META-INF/spring.factories file :

org.springframework.boot.SpringApplicationRunListener=my.ClasspathExtender
like image 26
gregfqt Avatar answered Sep 30 '22 19:09

gregfqt