How to really package and deploy a Spring Boot application

Packaging a Spring Boot application is very simple, just build it with maven or gradle and you are done. At least so I thought and then I wanted to add a MySQL driver at runtime. I do not want to add it in the original application jar, because the application should work with different databases and I don’t want to add “all possible” database drivers. Besides finding all possible database drivers is impossible and you would miss the one that is needed by one client. And if you try, the size of the fat jar would be unnecessary large.

Hoping for Spring does not work

So what’s the problem – just add the additional jar to the classpath with “-classpath”. No, that does not work, because you start the fat jar with “-jar” and Java documentation says: “When you use this option, the JAR file is the source of all user classes, and other user class path settings are ignored.”

OK, then we ask the almighty google for help and find the first result on a stackoverflow page: “You can use the loader.path property to define a lib folder location” There is also a link to the offical documentation. That’s great, but the first comment to the answer shows that it is not working. But why is it not working, the official documentation says it should work? After a little debugging I found that the main class that is started is not the needed PropertiesLauncher but the JarLauncher. Both can be used with an executable Jar, but only the first one supports the loader.path property. My first idea was to fix this via setting the Manifest Main-Class, but that did not work because the spring-boot-maven-plugin rewrites the main class in order to create the fat Jar. Although this was the wrong way, it lead me to the right one – through the documentation of the spring-boot-maven-plugin.

Manipulating the environment helps to bring an early Spring.

When I package a Spring application it should be possible to load some addition libraries at runtime. This is possible with the packaging layout ZIP instead of the default JAR. With this change it is possible to specify the property loader.path. For changing the layout, you need to add the following in your pom.xml:

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

There are several options for setting the loader.path properties, but I prefer it as a command line parameter. Because this way you set the profile you want to start and the path where all the other libs are:

java -Dspring.profiles.active=production -Dloader.path=lib -jar basel-server-0.0.2-SNAPSHOT.jar

Other possibilities are setting it in the manifest or in a loader.properties file. You can check this and the other PropertiesLancher Features in the documentation. I hope this helps with delpoying a spring application instead of just throwing a Jar somewhere.

By the way, the nice feature image of this blog post is made by my friend Marco Heisler, check out his other photos at 500px.com.

Leave a Reply