SCOPES = List.of(Artifact.SCOPE_COMPILE,
- Artifact.SCOPE_COMPILE_PLUS_RUNTIME, Artifact.SCOPE_RUNTIME);
-
- @Override
- public boolean include(Artifact artifact) {
- String scope = artifact.getScope();
- return !artifact.isOptional() && (scope == null || SCOPES.contains(scope));
- }
-
- }
-
}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java
similarity index 90%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java
index dc4ace66871..f4383ab65bd 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2025 the original author or authors.
+ * Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@
import org.apache.maven.project.MavenProjectHelper;
import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
+import org.jspecify.annotations.Nullable;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
@@ -46,7 +47,6 @@
import org.springframework.boot.loader.tools.Layouts.None;
import org.springframework.boot.loader.tools.Layouts.War;
import org.springframework.boot.loader.tools.Libraries;
-import org.springframework.boot.loader.tools.LoaderImplementation;
import org.springframework.boot.loader.tools.Packager;
import org.springframework.boot.loader.tools.layer.CustomLayers;
@@ -67,6 +67,7 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
* @since 1.0.0
*/
@Parameter(defaultValue = "${project}", readonly = true, required = true)
+ @SuppressWarnings("NullAway.Init")
protected MavenProject project;
/**
@@ -74,6 +75,7 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
* @since 2.4.0
*/
@Parameter(defaultValue = "${session}", readonly = true, required = true)
+ @SuppressWarnings("NullAway.Init")
protected MavenSession session;
/**
@@ -88,7 +90,7 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
* @since 1.0.0
*/
@Parameter
- private String mainClass;
+ private @Nullable String mainClass;
/**
* Exclude Spring Boot devtools from the repackaged archive.
@@ -111,6 +113,13 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
@Parameter(defaultValue = "false")
public boolean includeSystemScope;
+ /**
+ * Include optional dependencies.
+ * @since 3.5.7
+ */
+ @Parameter(defaultValue = "false")
+ public boolean includeOptional;
+
/**
* Include JAR tools.
* @since 3.3.0
@@ -135,16 +144,7 @@ protected AbstractPackagerMojo(MavenProjectHelper projectHelper) {
* @return {@code null}, indicating a layout type will be chosen based on the original
* archive type
*/
- protected LayoutType getLayout() {
- return null;
- }
-
- /**
- * Return the loader implementation that should be used.
- * @return the loader implementation or {@code null}
- * @since 3.2.0
- */
- protected LoaderImplementation getLoaderImplementation() {
+ protected @Nullable LayoutType getLayout() {
return null;
}
@@ -153,7 +153,7 @@ protected LoaderImplementation getLoaderImplementation() {
* no explicit layout is set.
* @return {@code null}, indicating a default layout factory will be chosen
*/
- protected LayoutFactory getLayoutFactory() {
+ protected @Nullable LayoutFactory getLayoutFactory() {
return null;
}
@@ -165,7 +165,6 @@ protected LayoutFactory getLayoutFactory() {
*/
protected P getConfiguredPackager(Supplier
supplier) {
P packager = supplier.get();
- packager.setLoaderImplementation(getLoaderImplementation());
packager.setLayoutFactory(getLayoutFactory());
packager.addMainClassTimeoutWarningListener(new LoggingMainClassTimeoutWarningListener(this::getLog));
packager.setMainClass(this.mainClass);
@@ -211,7 +210,7 @@ private Document getDocumentIfAvailable(File xmlFile) throws Exception {
* @return the libraries to use
* @throws MojoExecutionException on execution error
*/
- protected final Libraries getLibraries(Collection unpacks) throws MojoExecutionException {
+ protected final Libraries getLibraries(@Nullable Collection unpacks) throws MojoExecutionException {
Set artifacts = this.project.getArtifacts();
Set includedArtifacts = filterDependencies(artifacts, getAdditionalFilters());
return new ArtifactsLibraries(artifacts, includedArtifacts, this.session.getProjects(), unpacks, getLog());
@@ -228,6 +227,9 @@ private ArtifactsFilter[] getAdditionalFilters() {
if (!this.includeSystemScope) {
filters.add(new ScopeFilter(null, Artifact.SCOPE_SYSTEM));
}
+ if (!this.includeOptional) {
+ filters.add(DependencyFilter.exclude(Artifact::isOptional));
+ }
return filters.toArray(new ArtifactsFilter[0]);
}
@@ -238,12 +240,12 @@ private ArtifactsFilter[] getAdditionalFilters() {
* @param classifier the artifact classifier
* @return the source artifact to repackage
*/
- protected Artifact getSourceArtifact(String classifier) {
+ protected Artifact getSourceArtifact(@Nullable String classifier) {
Artifact sourceArtifact = getArtifact(classifier);
return (sourceArtifact != null) ? sourceArtifact : this.project.getArtifact();
}
- private Artifact getArtifact(String classifier) {
+ private @Nullable Artifact getArtifact(@Nullable String classifier) {
if (classifier != null) {
for (Artifact attachedArtifact : this.project.getAttachedArtifacts()) {
if (classifier.equals(attachedArtifact.getClassifier()) && attachedArtifact.getFile() != null
@@ -255,7 +257,7 @@ private Artifact getArtifact(String classifier) {
return null;
}
- protected File getTargetFile(String finalName, String classifier, File targetDirectory) {
+ protected File getTargetFile(String finalName, @Nullable String classifier, File targetDirectory) {
String classifierSuffix = (classifier != null) ? classifier.trim() : "";
if (!classifierSuffix.isEmpty() && !classifierSuffix.startsWith("-")) {
classifierSuffix = "-" + classifierSuffix;
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
similarity index 89%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
index 0595d130c40..08feb075567 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2025 the original author or authors.
+ * Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
@@ -36,8 +37,10 @@
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.toolchain.ToolchainManager;
+import org.jspecify.annotations.Nullable;
import org.springframework.boot.loader.tools.FileUtils;
+import org.springframework.util.StringUtils;
/**
* Base class to run a Spring Boot application.
@@ -60,6 +63,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.0.0
*/
@Parameter(defaultValue = "${project}", readonly = true, required = true)
+ @SuppressWarnings("NullAway.Init")
private MavenProject project;
/**
@@ -68,6 +72,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 2.3.0
*/
@Parameter(defaultValue = "${session}", readonly = true)
+ @SuppressWarnings("NullAway.Init")
private MavenSession session;
/**
@@ -95,6 +100,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 2.2.0
*/
@Parameter(property = "spring-boot.run.agents")
+ @SuppressWarnings("NullAway") // maven-maven-plugin can't handle annotated arrays
private File[] agents;
/**
@@ -112,7 +118,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.5.0
*/
@Parameter(property = "spring-boot.run.workingDirectory")
- private File workingDirectory;
+ private @Nullable File workingDirectory;
/**
* JVM arguments that should be associated with the forked process used to run the
@@ -121,7 +127,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.1.0
*/
@Parameter(property = "spring-boot.run.jvmArguments")
- private String jvmArguments;
+ private @Nullable String jvmArguments;
/**
* List of JVM system properties to pass to the process.
@@ -129,7 +135,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 2.1.0
*/
@Parameter
- private Map systemPropertyVariables;
+ private @Nullable Map systemPropertyVariables;
/**
* List of Environment variables that should be associated with the forked process
@@ -138,7 +144,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 2.1.0
*/
@Parameter
- private Map environmentVariables;
+ private @Nullable Map environmentVariables;
/**
* Arguments that should be passed to the application.
@@ -146,6 +152,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.0.0
*/
@Parameter
+ @SuppressWarnings("NullAway") // maven-maven-plugin can't handle annotated arrays
private String[] arguments;
/**
@@ -156,7 +163,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 2.2.3
*/
@Parameter(property = "spring-boot.run.arguments")
- private String commandlineArguments;
+ private @Nullable String commandlineArguments;
/**
* The spring profiles to activate. Convenience shortcut of specifying the
@@ -166,6 +173,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.3.0
*/
@Parameter(property = "spring-boot.run.profiles")
+ @SuppressWarnings("NullAway") // maven-maven-plugin can't handle annotated arrays
private String[] profiles;
/**
@@ -175,7 +183,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.0.0
*/
@Parameter(property = "spring-boot.run.main-class")
- private String mainClass;
+ private @Nullable String mainClass;
/**
* Additional classpath elements that should be added to the classpath. An element can
@@ -184,6 +192,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 3.2.0
*/
@Parameter(property = "spring-boot.run.additional-classpath-elements")
+ @SuppressWarnings("NullAway") // maven-maven-plugin can't handle annotated arrays
private String[] additionalClasspathElements;
/**
@@ -193,6 +202,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.0.0
*/
@Parameter(defaultValue = "${project.build.outputDirectory}", required = true)
+ @SuppressWarnings("NullAway.Init")
private File classesDirectory;
/**
@@ -302,17 +312,20 @@ private Map determineEnvironmentVariables() {
* @return a {@link RunArguments} defining the JVM arguments
*/
protected RunArguments resolveJvmArguments() {
- StringBuilder stringBuilder = new StringBuilder();
+ List<@Nullable String> arguments = new ArrayList<>();
if (this.systemPropertyVariables != null) {
- stringBuilder.append(this.systemPropertyVariables.entrySet()
- .stream()
- .map((e) -> SystemPropertyFormatter.format(e.getKey(), e.getValue()))
- .collect(Collectors.joining(" ")));
+ for (Entry systemProperty : this.systemPropertyVariables.entrySet()) {
+ String argument = SystemPropertyFormatter.format(systemProperty.getKey(), systemProperty.getValue());
+ if (StringUtils.hasText(argument)) {
+ arguments.add(argument);
+ }
+ }
}
if (this.jvmArguments != null) {
- stringBuilder.append(" ").append(this.jvmArguments);
+ String[] jvmArguments = RunArguments.parseArgs(this.jvmArguments);
+ arguments.addAll(Arrays.asList(jvmArguments));
}
- return new RunArguments(stringBuilder.toString());
+ return new RunArguments(arguments);
}
private void addJvmArgs(List args) {
@@ -336,7 +349,7 @@ private void addAgents(List args) {
}
private void addActiveProfileArgument(RunArguments arguments) {
- if (this.profiles.length > 0) {
+ if (this.profiles != null && this.profiles.length > 0) {
StringBuilder arg = new StringBuilder("--spring.profiles.active=");
for (int i = 0; i < this.profiles.length; i++) {
arg.append(this.profiles[i]);
@@ -419,21 +432,4 @@ private void logArguments(String name, String[] args) {
}
}
- /**
- * Format System properties.
- */
- static class SystemPropertyFormatter {
-
- static String format(String key, String value) {
- if (key == null) {
- return "";
- }
- if (value == null || value.isEmpty()) {
- return String.format("-D%s", key);
- }
- return String.format("-D%s=\"%s\"", key, value);
- }
-
- }
-
}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java
similarity index 95%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java
index e6573112e4e..8ed3efb08b7 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2023 the original author or authors.
+ * Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
+import org.jspecify.annotations.Nullable;
import org.springframework.boot.loader.tools.Libraries;
import org.springframework.boot.loader.tools.Library;
@@ -64,7 +65,7 @@ public class ArtifactsLibraries implements Libraries {
private final Collection localProjects;
- private final Collection unpacks;
+ private final @Nullable Collection unpacks;
private final Log log;
@@ -78,7 +79,7 @@ public class ArtifactsLibraries implements Libraries {
* @since 2.4.0
*/
public ArtifactsLibraries(Set artifacts, Collection localProjects,
- Collection unpacks, Log log) {
+ @Nullable Collection unpacks, Log log) {
this(artifacts, artifacts, localProjects, unpacks, log);
}
@@ -93,7 +94,7 @@ public ArtifactsLibraries(Set artifacts, Collection loca
* @since 2.4.8
*/
public ArtifactsLibraries(Set artifacts, Set includedArtifacts,
- Collection localProjects, Collection