Skip to content

Commit

Permalink
Allow to define parent first artifacts in fast jar mode
Browse files Browse the repository at this point in the history
  • Loading branch information
essobedo committed May 20, 2021
1 parent 96098d1 commit 0d900a7
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import io.quarkus.deployment.builditem.MainClassBuildItem;
import io.quarkus.deployment.builditem.QuarkusBuildCloseablesBuildItem;
import io.quarkus.deployment.builditem.TransformedClassesBuildItem;
import io.quarkus.deployment.configuration.ClassLoadingConfig;
import io.quarkus.deployment.pkg.PackageConfig;
import io.quarkus.deployment.pkg.builditem.AppCDSRequestedBuildItem;
import io.quarkus.deployment.pkg.builditem.ArtifactResultBuildItem;
Expand Down Expand Up @@ -203,6 +204,7 @@ public JarBuildItem buildRunnerJar(CurateOutcomeBuildItem curateOutcomeBuildItem
ApplicationArchivesBuildItem applicationArchivesBuildItem,
ApplicationInfoBuildItem applicationInfo,
PackageConfig packageConfig,
ClassLoadingConfig classLoadingConfig,
List<GeneratedClassBuildItem> generatedClasses,
List<GeneratedResourceBuildItem> generatedResources,
List<UberJarRequiredBuildItem> uberJarRequired,
Expand Down Expand Up @@ -234,7 +236,7 @@ public JarBuildItem buildRunnerJar(CurateOutcomeBuildItem curateOutcomeBuildItem
packageConfig, applicationInfo, generatedClasses, generatedResources, mainClassBuildItem);
} else {
return buildThinJar(curateOutcomeBuildItem, outputTargetBuildItem, transformedClasses, applicationArchivesBuildItem,
packageConfig, applicationInfo, generatedClasses, generatedResources,
packageConfig, classLoadingConfig, applicationInfo, generatedClasses, generatedResources,
additionalApplicationArchiveBuildItems, mainClassBuildItem);
}
}
Expand Down Expand Up @@ -509,6 +511,7 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem,
TransformedClassesBuildItem transformedClasses,
ApplicationArchivesBuildItem applicationArchivesBuildItem,
PackageConfig packageConfig,
ClassLoadingConfig classLoadingConfig,
ApplicationInfoBuildItem applicationInfo,
List<GeneratedClassBuildItem> generatedClasses,
List<GeneratedResourceBuildItem> generatedResources,
Expand Down Expand Up @@ -576,7 +579,7 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem,
}

List<Path> jars = new ArrayList<>();
List<Path> bootJars = new ArrayList<>();
List<Path> parentFirst = new ArrayList<>();
//we process in order of priority
//transformed classes first
if (!transformedClasses.getTransformedClassesByJar().isEmpty()) {
Expand Down Expand Up @@ -641,7 +644,7 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem,
}
}
}

final Set<AppArtifactKey> parentFirstKeys = getParentFirstKeys(curateOutcomeBuildItem, classLoadingConfig);
StringBuilder classPath = new StringBuilder();
for (AppDependency appDep : curateOutcomeBuildItem.getEffectiveModel().getUserDependencies()) {
if (rebuild) {
Expand All @@ -650,9 +653,8 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem,
copyDependency(curateOutcomeBuildItem, outputTargetBuildItem, copiedArtifacts, mainLib, baseLib, jars, true,
classPath, appDep);
}
if (curateOutcomeBuildItem.getEffectiveModel().getRunnerParentFirstArtifacts()
.contains(appDep.getArtifact().getKey())) {
bootJars.addAll(appDep.getArtifact().getPaths().toList());
if (parentFirstKeys.contains(appDep.getArtifact().getKey())) {
parentFirst.addAll(appDep.getArtifact().getPaths().toList());
}
}
for (AdditionalApplicationArchiveBuildItem i : additionalApplicationArchiveBuildItems) {
Expand Down Expand Up @@ -684,7 +686,8 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem,

Path appInfo = buildDir.resolve(QuarkusEntryPoint.QUARKUS_APPLICATION_DAT);
try (OutputStream out = Files.newOutputStream(appInfo)) {
SerializedApplication.write(out, mainClassBuildItem.getClassName(), buildDir, jars, bootJars, nonExistentResources);
SerializedApplication.write(out, mainClassBuildItem.getClassName(), buildDir, jars, parentFirst,
nonExistentResources);
}

runnerJar.toFile().setReadable(true, false);
Expand Down Expand Up @@ -774,6 +777,23 @@ public void accept(Path path) {
return new JarBuildItem(initJar, null, libDir, packageConfig.type, null);
}

/**
* @return a {@code Set} containing the key of the artifacts to load from the parent ClassLoader first.
*/
private Set<AppArtifactKey> getParentFirstKeys(CurateOutcomeBuildItem curateOutcomeBuildItem,
ClassLoadingConfig classLoadingConfig) {
final Set<AppArtifactKey> parentFirstKeys = new HashSet<>(
curateOutcomeBuildItem.getEffectiveModel().getRunnerParentFirstArtifacts());
classLoadingConfig.parentFirstArtifacts.ifPresent(
parentFirstArtifacts -> {
String[] artifacts = parentFirstArtifacts.split(",");
for (String artifact : artifacts) {
parentFirstKeys.add(new AppArtifactKey(artifact.split(":")));
}
});
return parentFirstKeys;
}

private boolean downloadFernflowerJar(PackageConfig packageConfig, Path fernflowerJar) {
String downloadURL = String.format("https://jitpack.io/com/github/fesh0r/fernflower/%s/fernflower-%s.jar",
packageConfig.fernflower.hash, packageConfig.fernflower.hash);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ void testMultiModuleAppRootWithNoSources()
ensureManifestOfJarIsReadableByJarInputStream(runnerJar);
}

@Test
void testClassLoaderLinkageError()
throws MavenInvocationException, IOException, InterruptedException {
testDir = initProject("projects/classloader-linkage-error", "projects/classloader-linkage-error-build");
build();
for (TestContext context : TestContext.values()) {
if (context == TestContext.FAST_NO_PREFIX) {
continue;
}
launch(context, "", "hello");
}
}

@Test
void testModuleWithBuildProfileInProperty() throws MavenInvocationException, InterruptedException, IOException {
testDir = initProject("projects/build-mode-quarkus-profile-property");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ public void testEnvironmentVariablesConfig() throws MavenInvocationException, IO
assertThat(DevModeTestUtils.getHttpResponse("/hello")).isEqualTo("hello, WORLD");
}

@Test
void testClassLoaderLinkageError()
throws MavenInvocationException, IOException, InterruptedException {
testDir = initProject("projects/classloader-linkage-error", "projects/classloader-linkage-error-dev");
run(true);
assertThat(DevModeTestUtils.getHttpResponse("/hello")).isEqualTo("hello");
}

@Test
public void testCapabilitiesConflict() throws MavenInvocationException, IOException {
testDir = getTargetDir("projects/capabilities-conflict");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.acme</groupId>
<artifactId>acme</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.version>@project.version@</quarkus.platform.version>
<quarkus-plugin.version>@project.version@</quarkus-plugin.version>
<maven.compiler.source>11</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>11</maven.compiler.target>
<jaxb.version>2.3.1</jaxb.version>
<jaxb-core.version>2.3.0.1</jaxb-core.version>
<stax-api.version>1.0.1</stax-api.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- insert managed dependencies here -->
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- insert test dependencies here -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>${jaxb-core.version}</version>
</dependency>
<dependency>
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
<version>${stax-api.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus-plugin.version}</version>
<executions>
<execution>
<id>fast-jar</id>
<goals>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
<goal>build</goal>
</goals>
<configuration>
<properties>
<quarkus.package.output-directory>fast-quarkus-app</quarkus.package.output-directory>
</properties>
</configuration>
</execution>
<execution>
<id>legacy-jar</id>
<goals>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
<goal>build</goal>
</goals>
<configuration>
<properties>
<quarkus.package.output-name>legacy</quarkus.package.output-name>
<quarkus.package.type>legacy-jar</quarkus.package.type>
<quarkus.package.output-directory>legacy-quarkus-app</quarkus.package.output-directory>
</properties>
</configuration>
</execution>
<execution>
<id>uber-jar</id>
<goals>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
<goal>build</goal>
</goals>
<configuration>
<properties>
<quarkus.package.output-name>uber</quarkus.package.output-name>
<quarkus.package.type>uber-jar</quarkus.package.type>
<quarkus.package.output-directory>uber-quarkus-app</quarkus.package.output-directory>
</properties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native</id>
<properties>
<quarkus.package.type>native</quarkus.package.type>
</properties>
</profile>
</profiles>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.acme;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import javax.xml.bind.JAXBContext;

@Path("/hello")
public class HelloResource {

@Inject
JAXBContext context;

@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "hello";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.acme;

import javax.enterprise.inject.Produces;
import javax.inject.Singleton;
import javax.xml.bind.JAXBContext;

public class Producer {

@Singleton
@Produces
protected JAXBContext createJAXBContext() throws Exception {
return JAXBContext.newInstance(); // This line causes the LinkageError
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
quarkus.class-loading.parent-first-artifacts=stax:stax-api

0 comments on commit 0d900a7

Please sign in to comment.