When an application is run as an executable archive with nested jars,
the application's own classes need to be able to load classes from
within the nested jars. This means that the application's classes need
to be loaded by the same class loader as is used for the nested jars.
When an application is launched with java -jar the contents of the
jar are on the class path of the app class loader, which is the
parent of the LaunchedURLClassLoader that is used to load classes
from within the nested jars. If the root of the jar includes the
application's classes, they would be loaded by the app class loader
and, therefore, would not be able to load classes from within the
nested jars.
Previously, this problem was resolved by LaunchedURLClassLoader being
created with a copy of all of the app class laoder's URLs and by
using an unconventional delegation model that caused it to skip its
parent (the app class loader) and jump straight to its root class
loader. This ensured that the LaunchedURLClassLoader would load both
the application's own classes and those from within any nested jars.
Unfortunately, this unusual delegation model has proved to be
problematic. We have seen and worked around some problems with Java
Agents (see gh-4911 and gh-863), but there are others (see gh-4868)
that cannot be made to work with the current delegation model.
This commit reworks LaunchedURLClassLoader to use a conventional
delegate model with the app class loader as its parent. With this
change in place, the application's own classes need to be hidden
from the app class loader via some other means. This is now achieved
by packaging application classes in BOOT-INF/classes (and, for
symmetry, nested jars are now packaged in BOOT-INF/lib). Both the
JarLauncher and the PropertiesLauncher (which supports the executable
jar layout) have been updated to look for classes and nested jars in
these new locations.
Closes gh-4897
Fixes gh-4868
Previously, the CLI’s dependency management used proprietary Properties
file-based metadata to configure its dependency management. Since
spring-boot-gradle-plugin’s move to using the separate dependency
management plugin the CLI was the only user of this format.
This commit updates the CLI to use Maven boms to configure its
dependency management. By default it uses the spring-boot-dependencies
bom. This configuration can be augmented and overridden using the new
@DependencyManagementBom annotation which replaces @GrabMetadata.
Closes gh-2688
Closes gh-2439
This commit adds a new command to the CLI that allows to initialize a new
project from the command line. It uses the Spring initializr service to
actually generate the project.
The command offers two main operations:
1. Listing the capabilities of the service (--list or -l). This basically
dumps the defaults of a given service and the list of dependencies and
project types it supports
2. Generating a project. By default, http://start.spring.io is used and
its configured defaults are applied. Running spring init would therefore
have the same effect as clicking the 'generate project' on the UI without
entering any extra information. No file is overwritten by default.
The generation can be customized with the following options:
* --boot-version (-bv) Spring Boot version the project should use
* --dependencies (-d) comma separated list of dependencies to add to the
generated project
* --java-version (-jv) Java version to use
* --packaging (-p) the packaging for the project (jar, war)
* --target the url of the service to use
The actual type of the project can be defined in several ways:
1. Using the --type (-t) option that identifies a type that is supported
by the service
2. A combination of --build and/or --format that can be used to uniquely
identify matching these tags. Build represents the build system to use
(e.g. maven or gradle) while --format defines the format of the generated
project.
The project is saved on disk with the name provided by the server through
the Content-Disposition header, if any. It is possible to force it with
the --output option. It is possible to overwrite existing files by adding
the --force (-f) flag.
The --extract (-x) option allows to extract the project instead of saving
the zip archive. By default, the project is extracted in the current
working directory but it is possible to specify an alternate directory
using the --output option.
Fixes gh-1751
Restore the dependency on commons-logging (transitively via spring-core)
for spring-boot. This means that we are not tied directly to SLF4J, but
it is still an option that can be used via `jcl-over-slf4j`.
The `spring-boot-starter-parent` continues to replace `commons-logging`
with `jcl-over-slf4j`.
Fixes gh-981
This commit harmonizes the dependency management of internal modules
so that versions can be omitted everywhere. Update the maven coordinates
to provide the full groupId for consistency
There was an issue with the generated poms for the dependency
tools (I'm not sure the generation step works if you don't
do "mvn clean"). Anyway I verified that it works and removed
the (now) unnecessary provided dependency from spring-boot-cli.
Fixes gh-362
This commit updates the CLI so that it will decrypt any encrypted
passwords in a user's Maven settings.xml file.
The code that performs the decrytion has a transitive dependency on
three types in Plexus' logging API. There are tens of different
artifacts containing this API available in Maven Central. Rather than
bloating the API with a dependency on a complete Plexus container,
which could perhaps be considered the primary source, a dependency on
a considerably smaller artifact has been introduced.
Closes#574
A new command, jar, has been added to the CLI. The command can be
used to create a self-contained executable JAR file from a CLI app.
Basic usage is:
spring jar <jar-name> <source-files>
For example:
spring jar my-app.jar *.groovy
The resulting jar will contain the classes generated by compiling the
source files, all of the application's dependencies, and entries
on the application's classpath.
By default a CLI application has the current working directory on
its classpath. This can be overridden using the --classpath option.
Any file that is referenced directly by the classpath is always
included in the jar. Any file that is found a result of being
contained within a directory that is on the classpath is subject to
filtering to determine whether or not it should be included. The
default includes are public/**, static/**, resources/**,
META-INF/**, *. The default excludes are .*, repository/**, build/**,
target/**. To be included in the jar, a file must match one of the
includes and none of the excludes. The filters can be overridden using
the --include and --exclude options.
Closes#241