Update docs to fully reflect BOOT-INF executable archive layout changes

Closes gh-5195
pull/5618/head
Andy Wilkinson 9 years ago
parent 0ba605dbb2
commit fc6c57413b

@ -46,7 +46,7 @@ Spring Boot Loader compatible jar files should be structured in the following wa
+-classes
| +-mycompany
| +-project
| +-YouClasses.class
| +-YourClasses.class
+-lib
+-dependency1.jar
+-dependency2.jar
@ -77,7 +77,7 @@ Spring Boot Loader compatible war files should be structured in the following wa
| +-com
| +-mycompany
| +-project
| +-YouClasses.class
| +-YourClasses.class
+-lib
| +-dependency1.jar
| +-dependency2.jar
@ -95,26 +95,26 @@ a traditional web container should be placed in `WEB-INF/lib-provided`.
[[executable-jar-jarfile]]
=== Spring Boot's "`JarFile`" class
The core class used to support loading nested jars is
`org.springframework.boot.loader.jar.JarFile`. It allows you load jar
content from a standard jar file, or from nested child jar data. When first loaded, the
`org.springframework.boot.loader.jar.JarFile`. It allows you to load jar
content from a standard jar file, or from nested child jar data. When first loaded, the
location of each `JarEntry` is mapped to a physical file offset of the outer jar:
[indent=0]
----
myapp.jar
+---------+---------------------+
| | /lib/mylib.jar |
| A.class |+---------+---------+|
| || B.class | B.class ||
| |+---------+---------+|
+---------+---------------------+
^ ^ ^
0063 3452 3980
+-------------------+-------------------------+
| /BOOT-INF/classes | /BOOT-INF/lib/mylib.jar |
|+-----------------+||+-----------+----------+|
|| A.class ||| B.class | C.class ||
|+-----------------+||+-----------+----------+|
+-------------------+-------------------------+
^ ^ ^
0063 3452 3980
----
The example above shows how `A.class` can be found in `myapp.jar` position `0063`.
`B.class` from the nested jar can actually be found in `myapp.jar` position `3452`
and `B.class` is at position `3980`.
The example above shows how `A.class` can be found in `/BOOT-INF/classes` in `myapp.jar`
position `0063`. `B.class` from the nested jar can actually be found in `myapp.jar`
position `3452` and `C.class` is at position `3980`.
Armed with this information, we can load specific nested entries by simply seeking to
the appropriate part of the outer jar. We don't need to unpack the archive and we
@ -141,11 +141,12 @@ file and it's used to setup an appropriate `URLClassLoader` and ultimately call
There are 3 launcher subclasses (`JarLauncher`, `WarLauncher` and `PropertiesLauncher`).
Their purpose is to load resources (`.class` files etc.) from nested jar files or war
files in directories (as opposed to explicitly on the classpath). In the case of the
`[Jar|War]Launcher` the nested paths are fixed (`+lib/*.jar+` and `+lib-provided/*.jar+` for
the war case) so you just add extra jars in those locations if you want more. The
`PropertiesLauncher` looks in `lib/` in your application archive by default, but you can
add additional locations by setting an environment variable `LOADER_PATH` or `loader.path`
files in directories (as opposed to explicitly on the classpath). In the case of
`JarLauncher` and `WarLauncher` the nested paths are fixed. `JarLauncher` looks in
`BOOT-INF/lib/` and `WarLauncher` looks in `WEB-INF/lib/` and `WEB-INF/lib-provided/` so
you just add extra jars in those locations if you want more. The `PropertiesLauncher`
looks in `BOOT-INF/lib/` in your application archive by default, but you can add
additional locations by setting an environment variable `LOADER_PATH` or `loader.path`
in `application.properties` (comma-separated list of directories or archives).
@ -242,7 +243,9 @@ Environment variables can be capitalized with underscore separators instead of p
the default) as long as `loader.config.location` is not specified.
* `loader.path` can contain directories (scanned recursively for jar and zip files),
archive paths, or wildcard patterns (for the default JVM behavior).
* `loader.path` (if empty) defaults to `lib` (meaning a local directory or a nested one if running from an archive). Because of this `PropertiesLauncher` behaves the same as `JarLauncher` when no additional configuration is provided.
* `loader.path` (if empty) defaults to `lib` (meaning a local directory or a nested one if
running from an archive). Because of this `PropertiesLauncher` behaves the same as
`JarLauncher` when no additional configuration is provided.
* Placeholder replacement is done from System and environment variables plus the
properties file itself on all values before use.

@ -2590,31 +2590,42 @@ details.
[[howto-build-an-executable-archive-with-ant]]
=== Build an executable archive from Ant without using spring-boot-antlib
To build with Ant you need to grab dependencies, compile and then create a jar or war
archive as normal. To make it executable you can either use the `spring-boot-antlib`
archive. To make it executable you can either use the `spring-boot-antlib`
module, or you can follow these instructions:
. Use the appropriate launcher as a `Main-Class`, e.g. `JarLauncher` for a jar file, and
specify the other properties it needs as manifest entries, principally a `Start-Class`.
. Add the runtime dependencies in a nested '`lib`' directory (for a jar) and the
`provided` (embedded container) dependencies in a nested `lib-provided` directory.
Remember *not* to compress the entries in the archive.
. If you are building a jar, package the application's classes and resources in a nested
`BOOT-INF/classes` directory. If you are building a war, package the application's
classes in a nested `WEB-INF/classes` directory as usual.
. Add the runtime dependencies in a nested `BOOT-INF/lib` directory for a jar or
`WEB-INF/lib` for a war. Remember *not* to compress the entries in the archive.
. Add the `provided` (embedded container) dependencies in a nested `BOOT-INF/lib`
directory for jar or `WEB-INF/lib-provided` for a war. Remember *not* to compress the
entries in the archive.
. Add the `spring-boot-loader` classes at the root of the archive (so the `Main-Class`
is available).
. Use the appropriate launcher, e.g. `JarLauncher` for a jar file, as a `Main-Class`
attribute in the manifest and specify the other properties it needs as manifest entries,
principally a `Start-Class`.
Example:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
[source,xml,indent=0]
----
<target name="build" depends="compile">
<copy todir="target/classes/lib">
<fileset dir="lib/runtime" />
</copy>
<jar destfile="target/spring-boot-sample-actuator-${spring-boot.version}.jar" compress="false">
<fileset dir="target/classes" />
<fileset dir="src/main/resources" />
<zipfileset src="lib/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
<jar destfile="target/${ant.project.name}-${spring-boot.version}.jar" compress="false">
<mappedresources>
<fileset dir="target/classes" />
<globmapper from="*" to="BOOT-INF/classes/*"/>
</mappedresources>
<mappedresources>
<fileset dir="src/main/resources" erroronmissingdir="false"/>
<globmapper from="*" to="BOOT-INF/classes/*"/>
</mappedresources>
<mappedresources>
<fileset dir="${lib.dir}/runtime" />
<globmapper from="*" to="BOOT-INF/lib/*"/>
</mappedresources>
<zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
<manifest>
<attribute name="Main-Class" value="org.springframework.boot.loader.JarLauncher" />
<attribute name="Start-Class" value="${start-class}" />
@ -2623,11 +2634,12 @@ Example:
</target>
----
The Actuator Sample has a `build.xml` that should work if you run it with
The {github-code}/spring-boot-samples/spring-boot-sample-ant[Ant Sample] has a
`build.xml` with a `manual` task that should work if you run it with
[indent=0,subs="verbatim,quotes,attributes"]
----
$ ant -lib <folder containing ivy-2.2.jar>
$ ant -lib <folder containing ivy-2.2.jar> clean manual
----
after which you can run the application with

@ -13,6 +13,7 @@
<property name="spring-boot.version" value="1.4.0.BUILD-SNAPSHOT" />
<property name="lib.dir" location="${basedir}/target/lib" />
<property name="start-class" value="sample.ant.SampleAntApplication" />
<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve pattern="${lib.dir}/[conf]/[artifact]-[type]-[revision].[ext]" />
@ -32,12 +33,8 @@
<javac srcdir="src/main/java" destdir="target/classes" classpathref="compile.classpath" />
</target>
<target name="clean-all" description="cleans all created files/dirs" depends="clean">
<delete dir="${lib.dir}" />
</target>
<target name="clean" description="cleans all class files">
<delete dir="target/classes" />
<target name="clean" description="cleans all created files/dirs">
<delete dir="target" />
</target>
<target name="build" depends="compile">
@ -47,4 +44,26 @@
</spring-boot:lib>
</spring-boot:exejar>
</target>
<!-- Manual equivalent of the build target -->
<target name="manual" depends="compile">
<jar destfile="target/${ant.project.name}-${spring-boot.version}.jar" compress="false">
<mappedresources>
<fileset dir="target/classes" />
<globmapper from="*" to="BOOT-INF/classes/*"/>
</mappedresources>
<mappedresources>
<fileset dir="src/main/resources" erroronmissingdir="false"/>
<globmapper from="*" to="BOOT-INF/classes/*"/>
</mappedresources>
<mappedresources>
<fileset dir="${lib.dir}/runtime" />
<globmapper from="*" to="BOOT-INF/lib/*"/>
</mappedresources>
<zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
<manifest>
<attribute name="Main-Class" value="org.springframework.boot.loader.JarLauncher" />
<attribute name="Start-Class" value="${start-class}" />
</manifest>
</jar>
</target>
</project>

@ -3,8 +3,10 @@
<configurations>
<conf name="compile" description="everything needed to compile this module" />
<conf name="runtime" extends="compile" description="everything needed to run this module" />
<conf name="loader" description="Spring Boot loader used when manually building an executable archive" />
</configurations>
<dependencies>
<dependency org="org.springframework.boot" name="spring-boot-starter" rev="${spring-boot.version}" conf="compile" />
<dependency org="org.springframework.boot" name="spring-boot-loader" rev="${spring-boot.version}" conf="loader->default" />
</dependencies>
</ivy-module>

Loading…
Cancel
Save