Skip to content

Commit

Permalink
Merge pull request #4314 from atomfrede/2819-add-graal-vm-native-image
Browse files Browse the repository at this point in the history
add graal vm native image support for jhipster lite
  • Loading branch information
pascalgrimaud authored Nov 13, 2022
2 parents dfcb600 + 772769f commit a78824a
Show file tree
Hide file tree
Showing 12 changed files with 202 additions and 4 deletions.
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,53 @@ To launch tests and integration tests:
./mvnw clean verify
```

## GraalVM Native Support

This project has been configured to let you generate either a lightweight container or a native executable. It is also possible to run your tests in a native image.
Lightweight Container with Cloud Native Buildpacks

If you're already familiar with Spring Boot container images support, this is the easiest way to get started.
Docker should be installed and configured on your machine prior to creating the image.

To create the image, run the following goal:

```
./mvnw spring-boot:build-image -Pnative
```

Then, you can run the app like any other container:

```
docker run -p 7471:7471 --rm docker.io/library/jhlite:<VERSION>
```

## Executable with Native Build Tools

Use this option if you want to explore more options such as running your tests in a native image.
The GraalVM native-image compiler should be installed and configured on your machine.

NOTE: GraalVM 22.3+ is required.

To create the executable, run the following goal:

```
./mvnw native:compile -Pnative -DskipTests
```

Then, you can run the app as follows:

```
./target/jhlite
```

You can also run your existing tests suite in a native image. This is an efficient way to validate the compatibility of your application.

To run your existing tests in a native image, run the following goal:

```
./mvnw test -PnativeTest
```

## Lint

We use multiple linters check and lint your code:
Expand Down
17 changes: 14 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
>
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0-RC2</version>
</parent>

<groupId>tech.jhipster.lite</groupId>
<artifactId>jhlite</artifactId>
<version>0.22.1-SNAPSHOT</version>
Expand Down Expand Up @@ -91,7 +97,6 @@
<nexus-staging-maven-plugin.version>1.6.13</nexus-staging-maven-plugin.version>
<start-class>tech.jhipster.lite.JHLiteApp</start-class>

<spring-boot.version>3.0.0-RC2</spring-boot.version>
<byte-buddy.version>1.12.18</byte-buddy.version>
<compiler-plugin.version>3.10.1</compiler-plugin.version>
<surefire-plugin.version>3.0.0-M7</surefire-plugin.version>
Expand Down Expand Up @@ -127,7 +132,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<version>${project.parent.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
Expand Down Expand Up @@ -680,7 +685,7 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<version>${project.parent.version}</version>
<executions>
<execution>
<goals>
Expand All @@ -689,6 +694,12 @@
</execution>
</executions>
<configuration>
<image>
<buildpacks>
<buildpack>gcr.io/paketo-buildpacks/bellsoft-liberica:9.9.0-ea</buildpack>
<buildpack>gcr.io/paketo-buildpacks/java-native-image</buildpack>
</buildpacks>
</image>
<mainClass>${start-class}</mainClass>
</configuration>
</plugin>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package tech.jhipster.lite.module.infrastructure.primary;

import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import tech.jhipster.lite.common.domain.Generated;
import tech.jhipster.lite.module.domain.landscape.JHipsterLandscapeElementType;

@Generated(reason = "Not testing native runtime hints")
class NativeHints implements RuntimeHintsRegistrar {

@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
hints
.reflection()
.registerType(RestJHipsterModuleProperties.class, MemberCategory.values())
.registerType(RestJHipsterLandscape.class, MemberCategory.values())
.registerType(RestJHipsterLandscapeLevel.class, MemberCategory.values())
.registerType(RestJHipsterLandscapeElement.class, MemberCategory.values())
.registerType(RestJHipsterLandscapeModule.class, MemberCategory.values())
.registerType(RestJHipsterLandscapeFeature.class, MemberCategory.values())
.registerType(RestJHipsterLandscapeDependency.class, MemberCategory.values())
.registerType(RestJHipsterModulePropertiesDefinition.class, MemberCategory.values())
.registerType(JHipsterLandscapeElementType.class, MemberCategory.values());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.springdoc.core.customizers.OpenApiCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportRuntimeHints;
import tech.jhipster.lite.common.domain.Enums;
import tech.jhipster.lite.module.domain.JHipsterModuleSlug;
import tech.jhipster.lite.module.domain.properties.JHipsterPropertyDefaultValue;
Expand All @@ -28,6 +29,7 @@
import tech.jhipster.lite.module.domain.resource.JHipsterModuleResource;
import tech.jhipster.lite.module.domain.resource.JHipsterModulesResources;

@ImportRuntimeHints(NativeHints.class)
@Configuration
class OpenApiModulesConfiguration {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package tech.jhipster.lite.module.infrastructure.secondary.git;

import org.eclipse.jgit.api.*;
import org.eclipse.jgit.internal.*;
import org.eclipse.jgit.lib.*;
import org.springframework.aot.hint.*;
import tech.jhipster.lite.common.domain.*;

@Generated(reason = "Not testing native runtime hints")
class NativeHints implements RuntimeHintsRegistrar {

@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
/*
Mimics quarkus native configuration. See https://github.com/quarkiverse/quarkus-jgit/blob/main/deployment/src/main/java/io/quarkus/jgit/deployment/JGitProcessor.java
Their calls to
ReflectiveClassBuildItem(true, true,
"org.eclipse.jgit.api.MergeCommand$FastForwardMode",
means methods, fields and constructors
*/
hints
.reflection()
.registerType(MergeCommand.FastForwardMode.class, MemberCategory.values())
.registerType(MergeCommand.FastForwardMode.Merge.class, MemberCategory.values())
.registerType(JGitText.class, MemberCategory.values())
.registerType(CoreConfig.AutoCRLF.class, MemberCategory.values())
.registerType(CoreConfig.CheckStat.class, MemberCategory.values())
.registerType(CoreConfig.EOL.class, MemberCategory.values())
.registerType(CoreConfig.EolStreamType.class, MemberCategory.values())
.registerType(CoreConfig.HideDotFiles.class, MemberCategory.values())
.registerType(CoreConfig.SymLinks.class, MemberCategory.values())
.registerType(CoreConfig.LogRefUpdates.class, MemberCategory.values());

// patterns for JGit and our own template files
hints.resources().registerPattern("org.eclipse.jgit.internal.JGitText").registerPattern("generator/**");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package tech.jhipster.lite.module.infrastructure.secondary.git;

import org.springframework.context.annotation.*;
import tech.jhipster.lite.common.domain.*;

@ImportRuntimeHints(NativeHints.class)
@Generated(reason = "Not testing native configuration")
@Configuration
class NativeJGitConfiguration {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package tech.jhipster.lite.module.infrastructure.secondary.javadependency;

import org.dom4j.DocumentFactory;
import org.dom4j.util.NonLazyDocumentFactory;
import org.dom4j.util.ProxyDocumentFactory;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import tech.jhipster.lite.common.domain.Generated;

@Generated(reason = "Not testing native runtime hints")
class NativeHints implements RuntimeHintsRegistrar {

@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
// Needed for xml reading and writing via dom4j
hints
.reflection()
.registerType(ProxyDocumentFactory.class, MemberCategory.values())
.registerType(DocumentFactory.class, MemberCategory.values())
.registerType(NonLazyDocumentFactory.class, MemberCategory.values());

// internal usage
hints.reflection().registerType(TypeReference.of("com.sun.org.apache.xpath.internal.functions.FuncLocalPart"), MemberCategory.values());

// patterns for our own template files
hints.resources().registerPattern("generator/**");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package tech.jhipster.lite.module.infrastructure.secondary.javadependency;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportRuntimeHints;
import tech.jhipster.lite.common.domain.Generated;

@ImportRuntimeHints(NativeHints.class)
@Generated(reason = "Not testing native configuration")
@Configuration
public class NativeJavaDependencyConfiguration {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package tech.jhipster.lite.project.infrastructure.secondary;

import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import tech.jhipster.lite.common.domain.Generated;
import tech.jhipster.lite.project.domain.history.ProjectAction;
import tech.jhipster.lite.project.domain.history.ProjectHistory;

@Generated(reason = "Not testing native runtime hints")
class NativeHints implements RuntimeHintsRegistrar {

@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
hints
.reflection()
.registerType(PersistedProjectHistory.class, MemberCategory.values())
.registerType(ProjectHistory.class, MemberCategory.values())
.registerType(ProjectAction.class, MemberCategory.values())
.registerType(PersistedProjectAction.class, MemberCategory.values());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportRuntimeHints;
import tech.jhipster.lite.common.domain.Generated;

@Configuration
@ImportRuntimeHints(NativeHints.class)
class ProjectFormatterConfiguration {

private static final Logger log = LoggerFactory.getLogger(ProjectFormatterConfiguration.class);
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/config/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ server.port=7471
springdoc.swagger-ui.operationsSorter=alpha,beta
springdoc.swagger-ui.tagsSorter=alpha
springdoc.swagger-ui.tryItOutEnabled=true
springdoc.enable-native-support=true

application.exception.details=false
application.exception.package=org.,java.,net.,javax.,com.,io.,de.,tech.jhipster.lite
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/logback-spring.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
<!-- jhipster-needle-logback-add-log -->

<!-- https://logback.qos.ch/manual/configuration.html#shutdownHook and https://jira.qos.ch/browse/LOGBACK-1090 -->
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook" />
<shutdownHook class="ch.qos.logback.core.hook.DefaultShutdownHook" />

<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
Expand Down

0 comments on commit a78824a

Please sign in to comment.