Skip to content

Commit

Permalink
[issue GoogleContainerTools#4175] SpringBootExplodedProcessor now use…
Browse files Browse the repository at this point in the history
…s JAR's Main-Class when creating the target image's entrypoint
  • Loading branch information
stefan-prange committed Jan 28, 2024
1 parent 440bd48 commit 7b4c062
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -135,14 +136,23 @@ public List<FileEntriesLayer> createLayers() throws IOException {
}

@Override
public ImmutableList<String> computeEntrypoint(List<String> jvmFlags) {
ImmutableList.Builder<String> entrypoint = ImmutableList.builder();
entrypoint.add("java");
entrypoint.addAll(jvmFlags);
entrypoint.add("-cp");
entrypoint.add(JarLayers.APP_ROOT.toString());
entrypoint.add("org.springframework.boot.loader.JarLauncher");
return entrypoint.build();
public ImmutableList<String> computeEntrypoint(List<String> jvmFlags) throws IOException {
try (JarFile jarFile = new JarFile(jarPath.toFile())) {
String mainClass =
jarFile.getManifest().getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
if (mainClass == null) {
throw new IllegalArgumentException(
"`Main-Class:` attribute for an application main class not defined in the input JAR's "
+ "manifest (`META-INF/MANIFEST.MF` in the JAR).");
}
ImmutableList.Builder<String> entrypoint = ImmutableList.builder();
entrypoint.add("java");
entrypoint.addAll(jvmFlags);
entrypoint.add("-cp");
entrypoint.add(JarLayers.APP_ROOT.toString());
entrypoint.add(mainClass);
return entrypoint.build();
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.google.cloud.tools.jib.cli.jar;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;

import com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath;
import com.google.cloud.tools.jib.api.buildplan.FileEntriesLayer;
Expand All @@ -43,6 +44,8 @@ public class SpringBootExplodedProcessorTest {
private static final String SPRING_BOOT_LAYERED_WITH_ALL_EMPTY_LAYERS_LISTED =
"jar/spring-boot/springboot_layered_allEmptyLayers.jar";
private static final String SPRING_BOOT_NOT_LAYERED = "jar/spring-boot/springboot_notLayered.jar";
private static final String SPRING_BOOT_NO_MANIFEST =
"jar/spring-boot/springboot_noMainClass_in_manifest.jar";
private static final Integer JAR_JAVA_VERSION = 0; // any value

@Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder();
Expand Down Expand Up @@ -239,27 +242,53 @@ public void testCreateLayers_nonLayered() throws IOException, URISyntaxException
}

@Test
public void testComputeEntrypoint() {
public void testComputeEntrypoint() throws URISyntaxException, IOException {
Path sampleSpringBootJar = Paths.get(Resources.getResource(SPRING_BOOT_LAYERED).toURI());
SpringBootExplodedProcessor bootProcessor =
new SpringBootExplodedProcessor(
Paths.get("ignored"), Paths.get("ignored"), JAR_JAVA_VERSION);
sampleSpringBootJar, Paths.get("ignored"), JAR_JAVA_VERSION);
ImmutableList<String> actualEntrypoint = bootProcessor.computeEntrypoint(new ArrayList<>());
assertThat(actualEntrypoint)
.isEqualTo(
ImmutableList.of("java", "-cp", "/app", "org.springframework.boot.loader.JarLauncher"));
ImmutableList.of(
"java", "-cp", "/app", "org.springframework.boot.loader.launch.JarLauncher"));
}

@Test
public void testComputeEntrypoint_withJvmFlags() {
public void testComputeEntrypoint_withJvmFlags() throws URISyntaxException, IOException {
Path sampleSpringBootJar = Paths.get(Resources.getResource(SPRING_BOOT_LAYERED).toURI());
SpringBootExplodedProcessor bootProcessor =
new SpringBootExplodedProcessor(
Paths.get("ignored"), Paths.get("ignored"), JAR_JAVA_VERSION);
sampleSpringBootJar, Paths.get("ignored"), JAR_JAVA_VERSION);
ImmutableList<String> actualEntrypoint =
bootProcessor.computeEntrypoint(ImmutableList.of("-jvm-flag"));
assertThat(actualEntrypoint)
.isEqualTo(
ImmutableList.of(
"java", "-jvm-flag", "-cp", "/app", "org.springframework.boot.loader.JarLauncher"));
"java",
"-jvm-flag",
"-cp",
"/app",
"org.springframework.boot.loader.launch.JarLauncher"));
}

@Test
public void testComputeEntrypoint_noMainClass() throws URISyntaxException {
Path layeredSpringBootJar = Paths.get(Resources.getResource(SPRING_BOOT_NO_MANIFEST).toURI());
SpringBootExplodedProcessor bootProcessor =
new SpringBootExplodedProcessor(
layeredSpringBootJar, Paths.get("ignored"), JAR_JAVA_VERSION);

IllegalArgumentException exception =
assertThrows(
IllegalArgumentException.class,
() -> bootProcessor.computeEntrypoint(ImmutableList.of()));

assertThat(exception)
.hasMessageThat()
.isEqualTo(
"`Main-Class:` attribute for an application main class not defined in the input JAR's manifest "
+ "(`META-INF/MANIFEST.MF` in the JAR).");
}

@Test
Expand Down
Binary file modified jib-cli/src/test/resources/jar/spring-boot/springboot_layered.jar
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified jib-cli/src/test/resources/jar/spring-boot/springboot_sample.jar
Binary file not shown.

0 comments on commit 7b4c062

Please sign in to comment.