Skip to content

Commit

Permalink
fix: ignore spring related classes in native build (#1063)
Browse files Browse the repository at this point in the history
Quarkus Spring-Data extension does not support JPA specification.
This change removes from the native build Hilla classes referencing
Spring Data classes to prevent failures during native image creation.
  • Loading branch information
mcollovati authored Nov 10, 2024
1 parent 8078e22 commit 5f9d61f
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import com.vaadin.hilla.push.PushEndpoint;
import io.quarkus.arc.deployment.ExcludedTypeBuildItem;
import io.quarkus.bootstrap.classloading.QuarkusClassLoader;
import io.quarkus.deployment.Capabilities;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
Expand All @@ -55,12 +56,14 @@
import io.quarkus.deployment.builditem.BytecodeTransformerBuildItem;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.GeneratedNativeImageClassBuildItem;
import io.quarkus.deployment.builditem.RemovedResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourcePatternsBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedPackageBuildItem;
import io.quarkus.deployment.pkg.NativeConfig;
import io.quarkus.gizmo.ClassCreator;
import io.quarkus.gizmo.MethodCreator;
import io.quarkus.maven.dependency.ArtifactKey;
import io.quarkus.undertow.deployment.ServletDeploymentManagerBuildItem;
import io.quarkus.vertx.http.deployment.DefaultRouteBuildItem;
import org.atmosphere.cache.UUIDBroadcasterCache;
Expand Down Expand Up @@ -123,6 +126,24 @@ void preventHillaSpringBeansDetection(BuildProducer<ExcludedTypeBuildItem> produ
producer.produce(new ExcludedTypeBuildItem(ServletDeployer.class.getName()));
}

/*
* Quarkus Spring-Data extension does not currently support JpaSpecificationExecutor.
* Hilla classes based on that API must be removed from the native build
* to prevent NoClassDefFound errors
* https://quarkus.io/guides/spring-data-jpa#what-is-currently-unsupported
*/
@BuildStep(onlyIf = IsNativeBuild.class)
void removeHillaSpringBasedClasses(Capabilities capabilities, BuildProducer<RemovedResourceBuildItem> producer) {
producer.produce(new RemovedResourceBuildItem(
ArtifactKey.of("com.vaadin", "hilla-endpoint", null, "jar"),
Set.of(
"com/vaadin/hilla/crud/CrudConfiguration.class",
"com/vaadin/hilla/crud/CrudRepositoryService.class",
"com/vaadin/hilla/crud/JpaFilterConverter.class",
"com/vaadin/hilla/crud/ListRepositoryService.class",
"com/vaadin/hilla/crud/PropertyStringFilterSpecification.class")));
}

/*
* If license-checker is not present at runtime, create stub Dau integration
* classes that thrown an exception if invoked. This will happen only if the
Expand Down Expand Up @@ -188,6 +209,7 @@ void generateDummyDauClassesIfLicenseCheckerIsNotPresent(

@BuildStep
void hillaNativeSupport(
Capabilities capabilities,
CombinedIndexBuildItem combinedIndex,
BuildProducer<NativeImageResourcePatternsBuildItem> nativeImageResource,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {
Expand All @@ -205,11 +227,15 @@ void hillaNativeSupport(
classes.add(index.getClassByName(PushEndpoint.class));
classes.addAll(getJsonClasses(index));

classes.add(index.getClassByName("org.springframework.data.repository.Repository"));
classes.add(index.getClassByName("org.springframework.data.repository.CrudRepository"));
classes.add(index.getClassByName("org.springframework.data.domain.Pageable"));
if (capabilities.isPresent(QuarkusHillaExtensionProcessor.SPRING_DATA_SUPPORT)) {
classes.add(index.getClassByName("org.springframework.data.repository.Repository"));
classes.add(index.getClassByName("org.springframework.data.repository.CrudRepository"));
classes.add(index.getClassByName("org.springframework.data.domain.Pageable"));
classes.add(index.getClassByName("org.springframework.data.domain.Specification"));
}

reflectiveClass.produce(ReflectiveClassBuildItem.builder(classes.stream()
.filter(Objects::nonNull)
.map(classInfo -> classInfo.name().toString())
.toArray(String[]::new))
.constructors()
Expand Down
2 changes: 2 additions & 0 deletions commons/hilla-shaded-deps/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@
<include>org/springframework/data/domain/Sort$Order.class</include>
<include>org/springframework/data/domain/Sort$NullHandling.class</include>
<include>org/springframework/data/domain/Unpaged.class</include>
<include>org/springframework/data/repository/CrudRepository.class</include>
<include>org/springframework/data/repository/Repository.class</include>
<include>org/springframework/data/util/Streamable.class</include>
<include>org/springframework/data/util/StreamUtils.class</include>
<include>org/springframework/data/util/LazyStreamable.class</include>
Expand Down
14 changes: 14 additions & 0 deletions commons/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,20 @@
<groupId>com.github.mcollovati</groupId>
<artifactId>hilla-shaded-deps</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.security</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.data</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.graalvm.sdk</groupId>
Expand Down

0 comments on commit 5f9d61f

Please sign in to comment.