[JAVA] Examine the contents of the WAR file generated by the project created by Spring Initializr

Overview

-Create a Gradle and Maven project with Spring Initializr and examine the contents of the generated WAR file.

Items specified in Spring Initializr

Project file structure

Remove the test code etc. from the project created by Spring Initializr to make the following file structure.

Gradle

├── build.gradle
├── settings.gradle
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           ├── MyappApplication.java
        │           └── ServletInitializer.java
        └── resources
            ├── application.properties
            ├── static
            └── templates

Maven

├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           ├── MyappApplication.java
        │           └── ServletInitializer.java
        └── resources
            ├── application.properties
            ├── static
            └── templates

difference

The contents are the same except for the configuration file.

$ diff -r gradle/myapp maven/myapp
Only in gradle/myapp: build.gradle
Only in maven/myapp: pom.xml
Only in gradle/myapp: settings.gradle

Build configuration file

Add the external library Apache PDFBox. This is to find out how external libraries other than Spring are stored in the WAR file.

Gradle (build.gradle)

plugins {
  id 'org.springframework.boot' version '2.2.6.RELEASE'
  id 'io.spring.dependency-management' version '1.0.9.RELEASE'
  id 'java'
  id 'war'
}

group = 'com.example'
version = '0.0.1'
sourceCompatibility = '11'

repositories {
  mavenCentral()
}

dependencies {
  // https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox
  implementation 'org.apache.pdfbox:pdfbox:2.0.19'
  implementation 'org.springframework.boot:spring-boot-starter-web'
  providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
}

Maven (pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.6.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <groupId>com.example</groupId>
  <artifactId>myapp</artifactId>
  <version>0.0.1</version>
  <packaging>war</packaging>
  <name>myapp</name>
  <description>MyApp project</description>

  <properties>
    <java.version>11</java.version>
  </properties>

  <dependencies>
    <!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox -->
    <dependency>
      <groupId>org.apache.pdfbox</groupId>
      <artifactId>pdfbox</artifactId>
      <version>2.0.19</version>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <scope>provided</scope>
    </dependency>
  </dependencies>

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

</project>

Project build and WAR file deployment

Gradle

Uses Gradle 6.3.

$ gradle build
$ unzip build/libs/myapp-0.0.1.war -d dest

Maven

Uses Apache Maven 3.6.3.

$ mvn package
$ unzip target/myapp-0.0.1.war -d dest

File structure in WAR file

--The class file created by compiling the source code goes into WEB-INF / classes --Spring related JAR files go into WEB-INF / lib --The JAR file of the external library goes to WEB-INF / lib (Apache PDFBox pdfbox-2.0.19.jar is in WEB-INF / lib) --Files that are considered unnecessary as WAR such as tomcat-embed-core-9.0.33.jar are in WEB-INF / lib-provided. --Spring Boot Loader class files go into org / springframework / boot / loader

Spring Boot executable Jar format -Document

Dependencies must be placed in a nested WEB-INF / lib directory. Dependencies that are required when running the built-in but are not needed when deploying to a traditional web container should be placed in WEB-INF / lib-provided.

Spring Boot executable Jar format -Document

Java does not provide a standard way to load nested jar files (that is, the jar files contained within the jar). This can be a problem if you need to distribute a self-contained application that can be run without deploying from the command line.

To solve this problem, many developers use "shaded" jar files. The shaded jar packages all the classes from all the jars into a single "uber jar". The problem with shaded jar files is that it's hard to see which libraries are actually included in your application. Also, problems can occur if multiple jars use the same filename (but with different content). Spring Boot takes a different approach and can actually nest jars directly.

Gradle

$ tree dest
dest
├── META-INF
│   └── MANIFEST.MF
├── WEB-INF
│   ├── classes
│   │   ├── application.properties
│   │   ├── com
│   │   │   └── example
│   │   │       ├── MyappApplication.class
│   │   │       └── ServletInitializer.class
│   │   ├── static
│   │   └── templates
│   ├── lib
│   │   ├── classmate-1.5.1.jar
│   │   ├── commons-logging-1.2.jar
│   │   ├── fontbox-2.0.19.jar
│   │   ├── hibernate-validator-6.0.18.Final.jar
│   │   ├── jackson-annotations-2.10.3.jar
│   │   ├── jackson-core-2.10.3.jar
│   │   ├── jackson-databind-2.10.3.jar
│   │   ├── jackson-datatype-jdk8-2.10.3.jar
│   │   ├── jackson-datatype-jsr310-2.10.3.jar
│   │   ├── jackson-module-parameter-names-2.10.3.jar
│   │   ├── jakarta.validation-api-2.0.2.jar
│   │   ├── jboss-logging-3.4.1.Final.jar
│   │   ├── jul-to-slf4j-1.7.30.jar
│   │   ├── log4j-api-2.12.1.jar
│   │   ├── log4j-to-slf4j-2.12.1.jar
│   │   ├── logback-classic-1.2.3.jar
│   │   ├── logback-core-1.2.3.jar
│   │   ├── pdfbox-2.0.19.jar
│   │   ├── slf4j-api-1.7.30.jar
│   │   ├── snakeyaml-1.25.jar
│   │   ├── spring-aop-5.2.5.RELEASE.jar
│   │   ├── spring-beans-5.2.5.RELEASE.jar
│   │   ├── spring-boot-2.2.6.RELEASE.jar
│   │   ├── spring-boot-autoconfigure-2.2.6.RELEASE.jar
│   │   ├── spring-boot-starter-2.2.6.RELEASE.jar
│   │   ├── spring-boot-starter-json-2.2.6.RELEASE.jar
│   │   ├── spring-boot-starter-logging-2.2.6.RELEASE.jar
│   │   ├── spring-boot-starter-validation-2.2.6.RELEASE.jar
│   │   ├── spring-boot-starter-web-2.2.6.RELEASE.jar
│   │   ├── spring-context-5.2.5.RELEASE.jar
│   │   ├── spring-core-5.2.5.RELEASE.jar
│   │   ├── spring-expression-5.2.5.RELEASE.jar
│   │   ├── spring-jcl-5.2.5.RELEASE.jar
│   │   ├── spring-web-5.2.5.RELEASE.jar
│   │   └── spring-webmvc-5.2.5.RELEASE.jar
│   └── lib-provided
│       ├── jakarta.annotation-api-1.3.5.jar
│       ├── spring-boot-starter-tomcat-2.2.6.RELEASE.jar
│       ├── tomcat-embed-core-9.0.33.jar
│       ├── tomcat-embed-el-9.0.33.jar
│       └── tomcat-embed-websocket-9.0.33.jar
└── org
    └── springframework
        └── boot
            └── loader
                ├── ExecutableArchiveLauncher.class
                ├── JarLauncher.class
                ├── LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class
                ├── LaunchedURLClassLoader.class
                ├── Launcher.class
                ├── MainMethodRunner.class
                ├── PropertiesLauncher$1.class
                ├── PropertiesLauncher$ArchiveEntryFilter.class
                ├── PropertiesLauncher$PrefixMatchingArchiveFilter.class
                ├── PropertiesLauncher.class
                ├── WarLauncher.class
                ├── archive
                │   ├── Archive$Entry.class
                │   ├── Archive$EntryFilter.class
                │   ├── Archive.class
                │   ├── ExplodedArchive$1.class
                │   ├── ExplodedArchive$FileEntry.class
                │   ├── ExplodedArchive$FileEntryIterator$EntryComparator.class
                │   ├── ExplodedArchive$FileEntryIterator.class
                │   ├── ExplodedArchive.class
                │   ├── JarFileArchive$EntryIterator.class
                │   ├── JarFileArchive$JarFileEntry.class
                │   └── JarFileArchive.class
                ├── data
                │   ├── RandomAccessData.class
                │   ├── RandomAccessDataFile$1.class
                │   ├── RandomAccessDataFile$DataInputStream.class
                │   ├── RandomAccessDataFile$FileAccess.class
                │   └── RandomAccessDataFile.class
                ├── jar
                │   ├── AsciiBytes.class
                │   ├── Bytes.class
                │   ├── CentralDirectoryEndRecord$1.class
                │   ├── CentralDirectoryEndRecord$Zip64End.class
                │   ├── CentralDirectoryEndRecord$Zip64Locator.class
                │   ├── CentralDirectoryEndRecord.class
                │   ├── CentralDirectoryFileHeader.class
                │   ├── CentralDirectoryParser.class
                │   ├── CentralDirectoryVisitor.class
                │   ├── FileHeader.class
                │   ├── Handler.class
                │   ├── JarEntry.class
                │   ├── JarEntryFilter.class
                │   ├── JarFile$1.class
                │   ├── JarFile$2.class
                │   ├── JarFile$JarFileType.class
                │   ├── JarFile.class
                │   ├── JarFileEntries$1.class
                │   ├── JarFileEntries$EntryIterator.class
                │   ├── JarFileEntries.class
                │   ├── JarURLConnection$1.class
                │   ├── JarURLConnection$2.class
                │   ├── JarURLConnection$CloseAction.class
                │   ├── JarURLConnection$JarEntryName.class
                │   ├── JarURLConnection.class
                │   ├── StringSequence.class
                │   └── ZipInflaterInputStream.class
                └── util
                    └── SystemPropertyUtils.class

17 directories, 99 files

Maven

$ tree dest
dest
├── META-INF
│   ├── MANIFEST.MF
│   └── maven
│       └── com.example
│           └── myapp
│               ├── pom.properties
│               └── pom.xml
├── WEB-INF
│   ├── classes
│   │   ├── application.properties
│   │   └── com
│   │       └── example
│   │           ├── MyappApplication.class
│   │           └── ServletInitializer.class
│   ├── lib
│   │   ├── classmate-1.5.1.jar
│   │   ├── commons-logging-1.2.jar
│   │   ├── fontbox-2.0.19.jar
│   │   ├── hibernate-validator-6.0.18.Final.jar
│   │   ├── jackson-annotations-2.10.3.jar
│   │   ├── jackson-core-2.10.3.jar
│   │   ├── jackson-databind-2.10.3.jar
│   │   ├── jackson-datatype-jdk8-2.10.3.jar
│   │   ├── jackson-datatype-jsr310-2.10.3.jar
│   │   ├── jackson-module-parameter-names-2.10.3.jar
│   │   ├── jakarta.annotation-api-1.3.5.jar
│   │   ├── jakarta.validation-api-2.0.2.jar
│   │   ├── jboss-logging-3.4.1.Final.jar
│   │   ├── jul-to-slf4j-1.7.30.jar
│   │   ├── log4j-api-2.12.1.jar
│   │   ├── log4j-to-slf4j-2.12.1.jar
│   │   ├── logback-classic-1.2.3.jar
│   │   ├── logback-core-1.2.3.jar
│   │   ├── pdfbox-2.0.19.jar
│   │   ├── slf4j-api-1.7.30.jar
│   │   ├── snakeyaml-1.25.jar
│   │   ├── spring-aop-5.2.5.RELEASE.jar
│   │   ├── spring-beans-5.2.5.RELEASE.jar
│   │   ├── spring-boot-2.2.6.RELEASE.jar
│   │   ├── spring-boot-autoconfigure-2.2.6.RELEASE.jar
│   │   ├── spring-boot-starter-2.2.6.RELEASE.jar
│   │   ├── spring-boot-starter-json-2.2.6.RELEASE.jar
│   │   ├── spring-boot-starter-logging-2.2.6.RELEASE.jar
│   │   ├── spring-boot-starter-validation-2.2.6.RELEASE.jar
│   │   ├── spring-boot-starter-web-2.2.6.RELEASE.jar
│   │   ├── spring-context-5.2.5.RELEASE.jar
│   │   ├── spring-core-5.2.5.RELEASE.jar
│   │   ├── spring-expression-5.2.5.RELEASE.jar
│   │   ├── spring-jcl-5.2.5.RELEASE.jar
│   │   ├── spring-web-5.2.5.RELEASE.jar
│   │   └── spring-webmvc-5.2.5.RELEASE.jar
│   └── lib-provided
│       ├── spring-boot-starter-tomcat-2.2.6.RELEASE.jar
│       ├── tomcat-embed-core-9.0.33.jar
│       ├── tomcat-embed-el-9.0.33.jar
│       └── tomcat-embed-websocket-9.0.33.jar
└── org
    └── springframework
        └── boot
            └── loader
                ├── ExecutableArchiveLauncher.class
                ├── JarLauncher.class
                ├── LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class
                ├── LaunchedURLClassLoader.class
                ├── Launcher.class
                ├── MainMethodRunner.class
                ├── PropertiesLauncher$1.class
                ├── PropertiesLauncher$ArchiveEntryFilter.class
                ├── PropertiesLauncher$PrefixMatchingArchiveFilter.class
                ├── PropertiesLauncher.class
                ├── WarLauncher.class
                ├── archive
                │   ├── Archive$Entry.class
                │   ├── Archive$EntryFilter.class
                │   ├── Archive.class
                │   ├── ExplodedArchive$1.class
                │   ├── ExplodedArchive$FileEntry.class
                │   ├── ExplodedArchive$FileEntryIterator$EntryComparator.class
                │   ├── ExplodedArchive$FileEntryIterator.class
                │   ├── ExplodedArchive.class
                │   ├── JarFileArchive$EntryIterator.class
                │   ├── JarFileArchive$JarFileEntry.class
                │   └── JarFileArchive.class
                ├── data
                │   ├── RandomAccessData.class
                │   ├── RandomAccessDataFile$1.class
                │   ├── RandomAccessDataFile$DataInputStream.class
                │   ├── RandomAccessDataFile$FileAccess.class
                │   └── RandomAccessDataFile.class
                ├── jar
                │   ├── AsciiBytes.class
                │   ├── Bytes.class
                │   ├── CentralDirectoryEndRecord$1.class
                │   ├── CentralDirectoryEndRecord$Zip64End.class
                │   ├── CentralDirectoryEndRecord$Zip64Locator.class
                │   ├── CentralDirectoryEndRecord.class
                │   ├── CentralDirectoryFileHeader.class
                │   ├── CentralDirectoryParser.class
                │   ├── CentralDirectoryVisitor.class
                │   ├── FileHeader.class
                │   ├── Handler.class
                │   ├── JarEntry.class
                │   ├── JarEntryFilter.class
                │   ├── JarFile$1.class
                │   ├── JarFile$2.class
                │   ├── JarFile$JarFileType.class
                │   ├── JarFile.class
                │   ├── JarFileEntries$1.class
                │   ├── JarFileEntries$EntryIterator.class
                │   ├── JarFileEntries.class
                │   ├── JarURLConnection$1.class
                │   ├── JarURLConnection$2.class
                │   ├── JarURLConnection$CloseAction.class
                │   ├── JarURLConnection$JarEntryName.class
                │   ├── JarURLConnection.class
                │   ├── StringSequence.class
                │   └── ZipInflaterInputStream.class
                └── util
                    └── SystemPropertyUtils.class

18 directories, 101 files

difference

It doesn't change much.

$ diff -r gradle/myapp/dest maven/myapp/dest
diff -r gradle/myapp/dest/META-INF/MANIFEST.MF maven/myapp/dest/META-INF/MANIFEST.MF
1a2,5
> Created-By: Maven Archiver 3.4.0
> Build-Jdk-Spec: 11
> Implementation-Title: myapp
> Implementation-Version: 0.0.1
Only in maven/myapp/dest/META-INF: maven
Only in gradle/myapp/dest/WEB-INF/classes: static
Only in gradle/myapp/dest/WEB-INF/classes: templates
Only in maven/myapp/dest/WEB-INF/lib: jakarta.annotation-api-1.3.5.jar
Only in gradle/myapp/dest/WEB-INF/lib-provided: jakarta.annotation-api-1.3.5.jar

Recommended Posts

Examine the contents of the WAR file generated by the project created by Spring Initializr
The contents of the data saved by CarrierWave.
JAVA: jar, aar, view the contents of the file
Take a quick look at Gradle and read the build.gradle generated by Spring Initializr
List the contents of categories created with Active Hash
[Java] Check the JDK version of the built war file
Test the contents of an Excel file with JUnit
Get the object name of the instance created by the new operator
Put the file in the properties of string in spring xml configuration
Deploy the application created by Spring Boot to Heroku (public) ②
Deploy the application created by Spring Boot to Heroku (public) ①
How to change the contents of the jar file without decompressing
Extract the uniquely identifying value of the table created by PostgreSQL
Part 4: Customize the behavior of OAuth 2.0 Login supported by Spring Security 5
Fix the file name of war to the one set in Maven