Over the years in web development there has been a lot of changes in the way we run , ship , and deploy spring boot applications . So Spring boot fat jar file is a pretty new concept in the modern era .
In my earlier development career when initial version of Spring was released we used to build and ship spring based projects and it used to take hell lot of time building jars and then deploy to an application server , but now server itself is packaged as a jar .
Fat jar is basically a concept of bundling jars.In spring boot applications the concept of fat jar is mostly used .The spring boot fat jar file has all the artifacts bundled together as jars so that it can be easily deployed and shipped .All the external and internal dependencies along with application level properties are bundled in one single jar.spring-boot-maven-plugin is responsible to carry out this huge task of packaging everything into a fat jar.
How Spring Boot Fat Jar Works
Spring Boot project is usually built as an executable JAR file by using a maven plugin that does all the dirty work . Have a look at how you can configure the maven plugin .
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.5.0</version> </dependency> </dependencies> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.5.0</version> </plugin> </plugins>
Now packaging all the jars into a single jar is not an easy process , because there could be conflicts in jar name , internal classes . So how this is done
In order to pack all jars in a single nested jar which is runnable using single command ,
All the dependent jar should also be packaged into a single jar , and they should be waived by which all the dependent jar are package inside a final runnable jar . So most developers uses the concept of shading .
The dependencies are renamed and the class files are relocated so that it can be bundled alongside with applications project code .It is basically packing of all the classes and and resources inside the dependent jars and packed them into a final runnable jars . This works fine in very simple scenarios but it becomes complicated when the class names are same and resources inside dependent or third party jars are same .
The concept of Uber is slightly different from shading. An Uber jar will contain all the application label classes as well as its dependent jar or any third party jars into single packaging jar. It wont rename any of the jars rather it will package all jars and load classes from dependent jars or application classes as required .
Spring Boot Way Of Loading Uber/Fat Jar
Spring boot follows the same approach but lets have a look how does it arranges your application level classess , dependent libraries .
In any spring boot related there it will have three different types of entities
- project classes
- third-party dependent jars
- and spring related ClassLoaders
In case of spring boot , let’s have a look how spring boot loads jars and classes while running your application. Have a look how a Spring Boot extracted ja looks like .
+----Spring-boot-1.0.0-SNAPSHOT.jar +--BOOT-INF +--lib -(Thirdparty jars and spring related jars) +-classes(Your application level classes) +--org.springframework.boot.loader ---WarLauncher ---JarLauncher +--archive --JarFileArchive
Spring boot contains different varieties of class loaders for different scenarios. first the spring boot class loader will load all the dependent jars and all the libraries into the classpath.
Then it loads your project related class files into the classpath.This is a significant difference by the way which eclipse and other IDE loads classes in classpath .In eclipse your project class is will be first loaded into the classpath and then the project related libraries or external jars .
Hence it is always suggested to check your application by running using fat jars before pushing your changes .
How Spring Boot Class Loader Works
While starting up spring boot loads
BOOT-INF/lib to start the server . Loading of the classes and jars from both the locations is done by
Now if we talk about the sequence ,
BOOT-INF/lib will be loaded first then
BOOT-INF/classes will be loaded .
But this doesn’t happens in case of any IDE ,all ide would load the classes in your package in the classpath then it loads any libraries or jars .Here spring has defined its own classloader . Have a look how we can define a custom classpath .
If you look at source code of LaunchedURLClassLoader ,which extends
java.net.URLClassLoader . The url that we are passing is the folder and libraries path . Now when classes are scanned the classes are loaded and the first resource will be loaded .