Relocate launcher classes

Create alternative launcher classes under the package
`org.springframework.boot.loader.launch` and use them in favor
of the previous location.

This update is designed to improve compatibility with future
changes in the loader.

Closes gh-37667
pull/37640/head
Phillip Webb 1 year ago
parent f947bad3f7
commit c22548982a

@ -44,7 +44,7 @@ COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
----
Assuming the above `Dockerfile` is in the current directory, your docker image can be built with `docker build .`, or optionally specifying the path to your application jar, as shown in the following example:

@ -28,8 +28,8 @@ The following shows an example of a `layers.idx` file:
- BOOT-INF/lib/library1.jar
- BOOT-INF/lib/library2.jar
- "spring-boot-loader":
- org/springframework/boot/loader/JarLauncher.class
- org/springframework/boot/loader/jar/JarEntry.class
- org/springframework/boot/loader/launch/JarLauncher.class
- ... <other classes>
- "snapshot-dependencies":
- BOOT-INF/lib/library3-SNAPSHOT.jar
- "application":

@ -13,7 +13,7 @@ One way to run an unpacked archive is by starting the appropriate launcher, as f
[source,shell,indent=0,subs="verbatim"]
----
$ jar -xf myapp.jar
$ java org.springframework.boot.loader.JarLauncher
$ java org.springframework.boot.loader.launch.JarLauncher
----
This is actually slightly faster on startup (depending on the size of the jar) than running from an unexploded archive.

@ -22,7 +22,7 @@ The following example shows a typical `MANIFEST.MF` for an executable jar file:
[indent=0]
----
Main-Class: org.springframework.boot.loader.JarLauncher
Main-Class: org.springframework.boot.loader.launch.JarLauncher
Start-Class: com.mycompany.project.MyApplication
----

@ -132,7 +132,7 @@ The printed banner is registered as a singleton bean under the following name: `
The `${application.version}` and `${application.formatted-version}` properties are only available if you are using Spring Boot launchers.
The values will not be resolved if you are running an unpacked jar and starting it with `java -cp <classpath> <mainclass>`.
This is why we recommend that you always launch unpacked jars using `java org.springframework.boot.loader.JarLauncher`.
This is why we recommend that you always launch unpacked jars using `java org.springframework.boot.loader.launch.JarLauncher`.
This will initialize the `application.*` banner variables before building the classpath and launching your app.
====

@ -290,7 +290,7 @@ The following example shows how to build an executable archive with Ant:
</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="Main-Class" value="org.springframework.boot.loader.launch.JarLauncher" />
<attribute name="Start-Class" value="${start-class}" />
</manifest>
</jar>

@ -61,7 +61,7 @@
<zipfileset src="${destdir}/dependency/spring-boot-loader.jar" />
<manifest>
<attribute name="Main-Class"
value="org.springframework.boot.loader.JarLauncher" />
value="org.springframework.boot.loader.launch.JarLauncher" />
<attribute name="Start-Class" value="${start-class}" />
<attribute name="Spring-Boot-Classes" value="BOOT-INF/classes/" />
<attribute name="Spring-Boot-Lib" value="BOOT-INF/lib/" />

@ -66,7 +66,7 @@ task fullJar(type: Jar) {
}
manifest {
attributes(
"Main-Class": "org.springframework.boot.loader.JarLauncher",
"Main-Class": "org.springframework.boot.loader.launch.JarLauncher",
"Start-Class": "org.springframework.boot.cli.SpringCli"
)
}

@ -59,7 +59,7 @@ set CMD_LINE_ARGS=%$
@rem Setup the command line
set CLASSPATH=%SPRING_HOME%\lib\*
"%JAVA_EXE%" %JAVA_OPTS% -cp "%CLASSPATH%" org.springframework.boot.loader.JarLauncher %CMD_LINE_ARGS%
"%JAVA_EXE%" %JAVA_OPTS% -cp "%CLASSPATH%" org.springframework.boot.loader.launch.JarLauncher %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell

@ -115,4 +115,4 @@ if $cygwin; then
fi
IFS=" " read -r -a javaOpts <<< "$JAVA_OPTS"
exec "${JAVA_HOME}/bin/java" "${javaOpts[@]}" -cp "$CLASSPATH" org.springframework.boot.loader.JarLauncher "$@"
exec "${JAVA_HOME}/bin/java" "${javaOpts[@]}" -cp "$CLASSPATH" org.springframework.boot.loader.launch.JarLauncher "$@"

@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-2023 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.
@ -33,7 +33,7 @@ import org.springframework.boot.loader.tools.JavaExecutable;
*/
class ForkProcessCommand extends RunProcessCommand {
private static final String MAIN_CLASS = "org.springframework.boot.loader.JarLauncher";
private static final String MAIN_CLASS = "org.springframework.boot.loader.launch.JarLauncher";
private final Command command;

@ -10,7 +10,7 @@ tasks.named("bootWar") {
// tag::properties-launcher[]
tasks.named("bootWar") {
manifest {
attributes 'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher'
attributes 'Main-Class': 'org.springframework.boot.loader.launch.PropertiesLauncher'
}
}
// end::properties-launcher[]

@ -12,7 +12,7 @@ tasks.named<BootWar>("bootWar") {
// tag::properties-launcher[]
tasks.named<BootWar>("bootWar") {
manifest {
attributes("Main-Class" to "org.springframework.boot.loader.PropertiesLauncher")
attributes("Main-Class" to "org.springframework.boot.loader.launch.PropertiesLauncher")
}
}
// end::properties-launcher[]

@ -61,9 +61,9 @@ class BootArchiveSupport {
static {
Set<String> defaultLauncherClasses = new HashSet<>();
defaultLauncherClasses.add("org.springframework.boot.loader.JarLauncher");
defaultLauncherClasses.add("org.springframework.boot.loader.PropertiesLauncher");
defaultLauncherClasses.add("org.springframework.boot.loader.WarLauncher");
defaultLauncherClasses.add("org.springframework.boot.loader.launch.JarLauncher");
defaultLauncherClasses.add("org.springframework.boot.loader.launch.PropertiesLauncher");
defaultLauncherClasses.add("org.springframework.boot.loader.launch.WarLauncher");
DEFAULT_LAUNCHER_CLASSES = Collections.unmodifiableSet(defaultLauncherClasses);
}

@ -49,7 +49,7 @@ import org.gradle.work.DisableCachingByDefault;
@DisableCachingByDefault(because = "Not worth caching")
public abstract class BootJar extends Jar implements BootArchive {
private static final String LAUNCHER = "org.springframework.boot.loader.JarLauncher";
private static final String LAUNCHER = "org.springframework.boot.loader.launch.JarLauncher";
private static final String CLASSES_DIRECTORY = "BOOT-INF/classes/";

@ -48,7 +48,7 @@ import org.gradle.work.DisableCachingByDefault;
@DisableCachingByDefault(because = "Not worth caching")
public abstract class BootWar extends War implements BootArchive {
private static final String LAUNCHER = "org.springframework.boot.loader.WarLauncher";
private static final String LAUNCHER = "org.springframework.boot.loader.launch.WarLauncher";
private static final String CLASSES_DIRECTORY = "WEB-INF/classes/";

@ -166,7 +166,7 @@ class PackagingDocumentationTests {
assertThat(file).isFile();
try (JarFile jar = new JarFile(file)) {
assertThat(jar.getManifest().getMainAttributes().getValue("Main-Class"))
.isEqualTo("org.springframework.boot.loader.PropertiesLauncher");
.isEqualTo("org.springframework.boot.loader.launch.PropertiesLauncher");
}
}

@ -270,7 +270,9 @@ abstract class AbstractBootArchiveTests<T extends Jar & BootArchive> {
void loaderIsWrittenToTheRootOfTheJarWhenUsingThePropertiesLauncher() throws IOException {
this.task.getMainClass().set("com.example.Main");
executeTask();
this.task.getManifest().getAttributes().put("Main-Class", "org.springframework.boot.loader.PropertiesLauncher");
this.task.getManifest()
.getAttributes()
.put("Main-Class", "org.springframework.boot.loader.launch.PropertiesLauncher");
try (JarFile jarFile = new JarFile(this.task.getArchiveFile().get().getAsFile())) {
assertThat(jarFile.getEntry("org/springframework/boot/loader/LaunchedURLClassLoader.class")).isNotNull();
assertThat(jarFile.getEntry("org/springframework/boot/loader/")).isNotNull();
@ -362,7 +364,7 @@ abstract class AbstractBootArchiveTests<T extends Jar & BootArchive> {
assertThat(jarFile.getManifest().getMainAttributes().getValue("Main-Class"))
.isEqualTo("com.example.CustomLauncher");
assertThat(jarFile.getManifest().getMainAttributes().getValue("Start-Class")).isEqualTo("com.example.Main");
assertThat(jarFile.getEntry("org/springframework/boot/loader/LaunchedURLClassLoader.class")).isNull();
assertThat(jarFile.getEntry("org/springframework/boot/loader/launch/LaunchedClassLoader.class")).isNull();
}
}

@ -41,7 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat;
class BootJarTests extends AbstractBootArchiveTests<BootJar> {
BootJarTests() {
super(BootJar.class, "org.springframework.boot.loader.JarLauncher", "BOOT-INF/lib/", "BOOT-INF/classes/",
super(BootJar.class, "org.springframework.boot.loader.launch.JarLauncher", "BOOT-INF/lib/", "BOOT-INF/classes/",
"BOOT-INF/");
}

@ -39,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
class BootWarTests extends AbstractBootArchiveTests<BootWar> {
BootWarTests() {
super(BootWar.class, "org.springframework.boot.loader.WarLauncher", "WEB-INF/lib/", "WEB-INF/classes/",
super(BootWar.class, "org.springframework.boot.loader.launch.WarLauncher", "WEB-INF/lib/", "WEB-INF/classes/",
"WEB-INF/");
}

@ -21,5 +21,5 @@ task explode(type: Sync) {
task launch(type: JavaExec) {
classpath = files(explode)
mainClass = 'org.springframework.boot.loader.JarLauncher'
mainClass = 'org.springframework.boot.loader.launch.JarLauncher'
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2021 the original author or authors.
* Copyright 2012-2023 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.
@ -66,7 +66,7 @@ public final class Layouts {
@Override
public String getLauncherClassName() {
return "org.springframework.boot.loader.JarLauncher";
return "org.springframework.boot.loader.launch.JarLauncher";
}
@Override
@ -108,7 +108,7 @@ public final class Layouts {
@Override
public String getLauncherClassName() {
return "org.springframework.boot.loader.PropertiesLauncher";
return "org.springframework.boot.loader.launch.PropertiesLauncher";
}
}
@ -148,7 +148,7 @@ public final class Layouts {
@Override
public String getLauncherClassName() {
return "org.springframework.boot.loader.WarLauncher";
return "org.springframework.boot.loader.launch.WarLauncher";
}
@Override

@ -105,7 +105,7 @@ abstract class AbstractPackagerTests<P extends Packager> {
execute(packager, NO_LIBRARIES);
Manifest actualManifest = getPackagedManifest();
assertThat(actualManifest.getMainAttributes().getValue("Main-Class"))
.isEqualTo("org.springframework.boot.loader.JarLauncher");
.isEqualTo("org.springframework.boot.loader.launch.JarLauncher");
assertThat(actualManifest.getMainAttributes().getValue("Start-Class")).isEqualTo("a.b.C");
assertThat(hasPackagedLauncherClasses()).isTrue();
}
@ -121,7 +121,7 @@ abstract class AbstractPackagerTests<P extends Packager> {
execute(packager, NO_LIBRARIES);
Manifest actualManifest = getPackagedManifest();
assertThat(actualManifest.getMainAttributes().getValue("Main-Class"))
.isEqualTo("org.springframework.boot.loader.JarLauncher");
.isEqualTo("org.springframework.boot.loader.launch.JarLauncher");
assertThat(actualManifest.getMainAttributes().getValue("Start-Class")).isEqualTo("a.b.C");
assertThat(hasPackagedLauncherClasses()).isTrue();
}
@ -133,7 +133,7 @@ abstract class AbstractPackagerTests<P extends Packager> {
execute(packager, NO_LIBRARIES);
Manifest actualManifest = getPackagedManifest();
assertThat(actualManifest.getMainAttributes().getValue("Main-Class"))
.isEqualTo("org.springframework.boot.loader.JarLauncher");
.isEqualTo("org.springframework.boot.loader.launch.JarLauncher");
assertThat(actualManifest.getMainAttributes().getValue("Start-Class")).isEqualTo("a.b.C");
assertThat(hasPackagedLauncherClasses()).isTrue();
}
@ -684,7 +684,7 @@ abstract class AbstractPackagerTests<P extends Packager> {
protected boolean hasPackagedLauncherClasses() throws IOException {
return hasPackagedEntry("org/springframework/boot/")
&& hasPackagedEntry("org/springframework/boot/loader/JarLauncher.class");
&& hasPackagedEntry("org/springframework/boot/loader/launch/JarLauncher.class");
}
private boolean hasPackagedEntry(String name) throws IOException {

@ -79,7 +79,7 @@ class RepackagerTests extends AbstractPackagerTests<Repackager> {
repackager.repackage(NO_LIBRARIES);
Manifest actualManifest = getPackagedManifest();
assertThat(actualManifest.getMainAttributes().getValue("Main-Class"))
.isEqualTo("org.springframework.boot.loader.JarLauncher");
.isEqualTo("org.springframework.boot.loader.launch.JarLauncher");
assertThat(actualManifest.getMainAttributes().getValue("Start-Class")).isEqualTo("a.b.C");
assertThat(hasPackagedLauncherClasses()).isTrue();
}
@ -220,7 +220,7 @@ class RepackagerTests extends AbstractPackagerTests<Repackager> {
private boolean hasLauncherClasses(File file) throws IOException {
return hasEntry(file, "org/springframework/boot/")
&& hasEntry(file, "org/springframework/boot/loader/JarLauncher.class");
&& hasEntry(file, "org/springframework/boot/loader/launch/JarLauncher.class");
}
private boolean hasEntry(File file, String name) throws IOException {

@ -0,0 +1,34 @@
/*
* Copyright 2012-2023 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.loader.launch;
/**
* Repackaged {@link org.springframework.boot.loader.JarLauncher}.
*
* @author Phillip Webb
* @since 3.2.0
*/
public final class JarLauncher {
private JarLauncher() {
}
public static void main(String[] args) throws Exception {
org.springframework.boot.loader.JarLauncher.main(args);
}
}

@ -0,0 +1,34 @@
/*
* Copyright 2012-2023 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.loader.launch;
/**
* Repackaged {@link org.springframework.boot.loader.PropertiesLauncher}.
*
* @author Phillip Webb
* @since 3.2.0
*/
public final class PropertiesLauncher {
private PropertiesLauncher() {
}
public static void main(String[] args) throws Exception {
org.springframework.boot.loader.PropertiesLauncher.main(args);
}
}

@ -0,0 +1,34 @@
/*
* Copyright 2012-2023 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.loader.launch;
/**
* Repackaged {@link org.springframework.boot.loader.WarLauncher}.
*
* @author Phillip Webb
* @since 3.2.0
*/
public final class WarLauncher {
private WarLauncher() {
}
public static void main(String[] args) throws Exception {
org.springframework.boot.loader.WarLauncher.main(args);
}
}

@ -0,0 +1,23 @@
/*
* Copyright 2012-2023 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Repackaged launcher classes.
*
* @see org.springframework.boot.loader.launch.JarLauncher
* @see org.springframework.boot.loader.launch.WarLauncher
*/
package org.springframework.boot.loader.launch;

@ -57,7 +57,7 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests {
File repackaged = new File(project, "target/jar-0.0.1.BUILD-SNAPSHOT.jar");
assertThat(launchScript(repackaged)).isEmpty();
assertThat(jar(repackaged)).manifest((manifest) -> {
manifest.hasMainClass("org.springframework.boot.loader.JarLauncher");
manifest.hasMainClass("org.springframework.boot.loader.launch.JarLauncher");
manifest.hasStartClass("some.random.Main");
manifest.hasAttribute("Not-Used", "Foo");
})
@ -66,7 +66,7 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests {
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-jcl")
.hasEntryWithNameStartingWith("BOOT-INF/lib/jakarta.servlet-api-6")
.hasEntryWithName("BOOT-INF/classes/org/test/SampleApplication.class")
.hasEntryWithName("org/springframework/boot/loader/JarLauncher.class");
.hasEntryWithName("org/springframework/boot/loader/launch/JarLauncher.class");
assertThat(buildLog(project))
.contains("Replacing main artifact " + repackaged + " with repackaged archive,")
.contains("The original artifact has been renamed to " + original)
@ -273,9 +273,9 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests {
.goals("package", "-Dspring-boot.repackage.layout=ZIP")
.execute((project) -> {
File main = new File(project, "target/jar-with-layout-property-0.0.1.BUILD-SNAPSHOT.jar");
assertThat(jar(main))
.manifest((manifest) -> manifest.hasMainClass("org.springframework.boot.loader.PropertiesLauncher")
.hasStartClass("org.test.SampleApplication"));
assertThat(jar(main)).manifest(
(manifest) -> manifest.hasMainClass("org.springframework.boot.loader.launch.PropertiesLauncher")
.hasStartClass("org.test.SampleApplication"));
assertThat(buildLog(project)).contains("Layout: ZIP");
});
}
@ -284,9 +284,9 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests {
void whenALayoutIsConfiguredTheSpecifiedLayoutIsUsed(MavenBuild mavenBuild) {
mavenBuild.project("jar-with-zip-layout").execute((project) -> {
File main = new File(project, "target/jar-with-zip-layout-0.0.1.BUILD-SNAPSHOT.jar");
assertThat(jar(main))
.manifest((manifest) -> manifest.hasMainClass("org.springframework.boot.loader.PropertiesLauncher")
.hasStartClass("org.test.SampleApplication"));
assertThat(jar(main)).manifest(
(manifest) -> manifest.hasMainClass("org.springframework.boot.loader.launch.PropertiesLauncher")
.hasStartClass("org.test.SampleApplication"));
assertThat(buildLog(project)).contains("Layout: ZIP");
});
}

@ -57,10 +57,10 @@ class WarIntegrationTests extends AbstractArchiveIntegrationTests {
.hasEntryWithNameStartingWith("WEB-INF/lib/spring-core")
.hasEntryWithNameStartingWith("WEB-INF/lib/spring-jcl")
.hasEntryWithNameStartingWith("WEB-INF/lib-provided/jakarta.servlet-api-6")
.hasEntryWithName("org/springframework/boot/loader/WarLauncher.class")
.hasEntryWithName("org/springframework/boot/loader/launch/WarLauncher.class")
.hasEntryWithName("WEB-INF/classes/org/test/SampleApplication.class")
.hasEntryWithName("index.html")
.manifest((manifest) -> manifest.hasMainClass("org.springframework.boot.loader.WarLauncher")
.manifest((manifest) -> manifest.hasMainClass("org.springframework.boot.loader.launch.WarLauncher")
.hasStartClass("org.test.SampleApplication")
.hasAttribute("Not-Used", "Foo")));
}

@ -93,9 +93,10 @@ class PaketoBuilderTests {
.contains("paketo-buildpacks/ca-certificates", "paketo-buildpacks/bellsoft-liberica",
"paketo-buildpacks/executable-jar", "paketo-buildpacks/dist-zip",
"paketo-buildpacks/spring-boot");
metadata.processOfType("web").containsExactly("java", "org.springframework.boot.loader.JarLauncher");
metadata.processOfType("web")
.containsExactly("java", "org.springframework.boot.loader.launch.launch.JarLauncher");
metadata.processOfType("executable-jar")
.containsExactly("java", "org.springframework.boot.loader.JarLauncher");
.containsExactly("java", "org.springframework.boot.loader.launch.launch.JarLauncher");
});
assertImageHasJvmSbomLayer(imageReference, config);
assertImageHasDependenciesSbomLayer(imageReference, config, "executable-jar");
@ -238,9 +239,10 @@ class PaketoBuilderTests {
.contains("paketo-buildpacks/ca-certificates", "paketo-buildpacks/bellsoft-liberica",
"paketo-buildpacks/executable-jar", "paketo-buildpacks/dist-zip",
"paketo-buildpacks/spring-boot");
metadata.processOfType("web").containsExactly("java", "org.springframework.boot.loader.WarLauncher");
metadata.processOfType("web")
.containsExactly("java", "org.springframework.boot.loader.launch.WarLauncher");
metadata.processOfType("executable-jar")
.containsExactly("java", "org.springframework.boot.loader.WarLauncher");
.containsExactly("java", "org.springframework.boot.loader.launch.WarLauncher");
});
assertImageHasJvmSbomLayer(imageReference, config);
assertImageHasDependenciesSbomLayer(imageReference, config, "executable-jar");

@ -1,5 +1,5 @@
/*
* Copyright 2012-2021 the original author or authors.
* Copyright 2012-2023 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.
@ -55,8 +55,8 @@ class ExplodedApplicationLauncher extends AbstractApplicationLauncher {
@Override
protected List<String> getArguments(File archive, File serverPortFile) {
String mainClass = (archive.getName().endsWith(".war") ? "org.springframework.boot.loader.WarLauncher"
: "org.springframework.boot.loader.JarLauncher");
String mainClass = (archive.getName().endsWith(".war") ? "org.springframework.boot.loader.launch.WarLauncher"
: "org.springframework.boot.loader.launch.JarLauncher");
try {
explodeArchive(archive);
return Arrays.asList("-cp", this.exploded.getAbsolutePath(), mainClass, serverPortFile.getAbsolutePath());

@ -67,7 +67,7 @@
</mappedresources>
<zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${ant-spring-boot.version}.jar" />
<manifest>
<attribute name="Main-Class" value="org.springframework.boot.loader.JarLauncher" />
<attribute name="Main-Class" value="org.springframework.boot.loader.launch.JarLauncher" />
<attribute name="Start-Class" value="${start-class}" />
</manifest>
</jar>

Loading…
Cancel
Save