|
| 1 | +--- |
| 2 | +layout: ni-docs |
| 3 | +toc_group: how-to-guides |
| 4 | +link_title: Build a Native Executable from a Spring Boot Application |
| 5 | +permalink: /reference-manual/native-image/guides/build-spring-boot-app-into-native-executable/ |
| 6 | +--- |
| 7 | + |
| 8 | +# Build a Native Executable from a Spring Boot Application |
| 9 | + |
| 10 | +GraalVM Native Image can significantly boost the performance of a Spring Boot application. |
| 11 | +Spring Boot 3 has integrated support for GraalVM Native Image, making it easier to set up and configure your project. |
| 12 | + |
| 13 | +This guide demonstrates how to build a native executable from a Spring Boot 3 application. |
| 14 | + |
| 15 | +## Create an Application |
| 16 | + |
| 17 | +For the demo part, you will create a simple REST server Java application. |
| 18 | + |
| 19 | +1. Go to [Spring Initializr](https://start.spring.io/#!dependencies=native,web){:target="_blank"} and create a new Spring Boot project. |
| 20 | +Ensure to add the **GraalVM Native Support** and **Spring Web** dependencies. |
| 21 | + |
| 22 | +2. Click GENERATE to create and download the project as a _.zip_ file. Unzip the file and open it in your favorite IDE. |
| 23 | + |
| 24 | + The project configuration already contains all necessary dependencies and plugins, including [Native Build Tools](https://graalvm.github.io/native-build-tools/latest/index.html){:target="_blank"}. |
| 25 | + For example, if you created a Maven project, these are the required plugins added in the _pom.xml_ file: |
| 26 | + ```xml |
| 27 | + <build> |
| 28 | + <plugins> |
| 29 | + <plugin> |
| 30 | + <groupId>org.graalvm.buildtools</groupId> |
| 31 | + <artifactId>native-maven-plugin</artifactId> |
| 32 | + </plugin> |
| 33 | + <plugin> |
| 34 | + <groupId>org.springframework.boot</groupId> |
| 35 | + <artifactId>spring-boot-maven-plugin</artifactId> |
| 36 | + </plugin> |
| 37 | + </plugins> |
| 38 | + </build> |
| 39 | + ``` |
| 40 | + |
| 41 | +3. The main application class was created by the initializer. In the same directory, create a REST controller in a file named _HelloController.java_ with the following contents: |
| 42 | + ```java |
| 43 | + package com.example.demo; |
| 44 | + |
| 45 | + import org.springframework.web.bind.annotation.GetMapping; |
| 46 | + import org.springframework.web.bind.annotation.RestController; |
| 47 | + |
| 48 | + @RestController |
| 49 | + public class HelloController { |
| 50 | + |
| 51 | + @GetMapping("/hello") |
| 52 | + public String hello() { |
| 53 | + return "Hello, GraalVM!"; |
| 54 | + } |
| 55 | + } |
| 56 | + ``` |
| 57 | + |
| 58 | +4. (Optional) Package and run the application on a Java HotSpot Virtual Machine. |
| 59 | + Maven: |
| 60 | + ```bash |
| 61 | + ./mvnw spring-boot:run |
| 62 | + ``` |
| 63 | + Gradle: |
| 64 | + ```bash |
| 65 | + ./gradlew bootRun |
| 66 | + ``` |
| 67 | + It compiles the application, creates a JAR file, and runs the application. |
| 68 | + |
| 69 | + The application starts in hundreds of milliseconds. |
| 70 | + Open a browser and navigate to [localhost:8080/hello](http://localhost:8080/hello){:target="_blank"} to see the application running. |
| 71 | + You should see "Hello, GraalVM!". |
| 72 | + |
| 73 | +## Build a Native Executable Using Paketo Buildpacks |
| 74 | + |
| 75 | +Spring Boot supports building container images containing native executables using the [Paketo Buildpack for Oracle](https://github.com/paketo-buildpacks/oracle) which provides GraalVM Native Image. |
| 76 | + |
| 77 | +### Prerequisite |
| 78 | +Make sure you have a Docker-API compatible container runtime such as [Rancher Desktop](https://docs.rancherdesktop.io/getting-started/installation/){:target="_blank"} or [Docker](https://www.docker.com/gettingstarted/){:target="_blank"} installed and running. |
| 79 | + |
| 80 | +1. First, enable the [Paketo Buildpack for Oracle](https://github.com/paketo-buildpacks/oracle){:target="_blank"} requesting the Native Image tool. |
| 81 | + |
| 82 | + - **Maven**. Open the _pom.xml_ file, find the `spring-boot-maven-plugin` declaration, and change it so that it looks like this: |
| 83 | + ```xml |
| 84 | + <plugin> |
| 85 | + <groupId>org.springframework.boot</groupId> |
| 86 | + <artifactId>spring-boot-maven-plugin</artifactId> |
| 87 | + <configuration> |
| 88 | + <image> |
| 89 | + <builder>paketobuildpacks/builder-jammy-buildpackless-tiny</builder><!--required for AArch64/M1 support --> |
| 90 | + <buildpacks> |
| 91 | + <buildpack>paketobuildpacks/oracle</buildpack> |
| 92 | + <buildpack>paketobuildpacks/java-native-image</buildpack> |
| 93 | + </buildpacks> |
| 94 | + </image> |
| 95 | + </configuration> |
| 96 | + </plugin> |
| 97 | + ``` |
| 98 | + |
| 99 | + You should also ensure that your _pom.xml_ file uses `spring-boot-starter-parent`. |
| 100 | + The `<parent>` section should have been added by the initializer. |
| 101 | + |
| 102 | + - **Gradle**. Open the _build.gradle_ file, and add the following lines: |
| 103 | + ``` |
| 104 | + bootBuildImage { |
| 105 | + builder = "paketobuildpacks/builder-jammy-buildpackless-tiny" |
| 106 | + buildpacks = ["paketobuildpacks/oracle", "paketobuildpacks/java-native-image"] |
| 107 | + } |
| 108 | + ``` |
| 109 | + When `java-native-image` is requested, the buildpack downloads Oracle GraalVM, which includes Native Image. |
| 110 | + |
| 111 | +2. Build a native executable for this Spring application using buildpacks: |
| 112 | + - Maven: |
| 113 | + ```bash |
| 114 | + ./mvnw -Pnative spring-boot:build-image |
| 115 | + ``` |
| 116 | + |
| 117 | + - Gradle: |
| 118 | + ```bash |
| 119 | + ./gradlew bootBuildImage |
| 120 | + ``` |
| 121 | + |
| 122 | +3. Once the build completes, a Docker image should be available. You can start your application using `docker run`. For example: |
| 123 | + ```bash |
| 124 | + docker run --rm -p 8080:8080 docker.io/library/demo:0.0.1-SNAPSHOT |
| 125 | + ``` |
| 126 | + |
| 127 | +The [Paketo documentation provides several examples](https://paketo.io/docs/howto/java/#build-an-app-as-a-graalvm-native-image-application){:target="_blank"} that show you how to build applications with GraalVM Native Image using buildpacks. |
| 128 | + |
| 129 | +## Build a Native Executable Using Native Build Tools |
| 130 | + |
| 131 | +If you do not want to use Docker and create a native executable on a host machine, use [Native Build Tools](https://graalvm.github.io/native-build-tools/latest/index.html){:target="_blank"} which provide Maven and Gradle plugins for building native images. |
| 132 | + |
| 133 | +### Prerequisite |
| 134 | +Make sure you have installed a GraalVM JDK. |
| 135 | +The easiest way to get started is with [SDKMAN!](https://sdkman.io/jdks#graal){:target="_blank"}: |
| 136 | +```bash |
| 137 | +sdk install java 21.0.4-graal |
| 138 | +``` |
| 139 | +Substitute `21.0.4` with a preferred GraalVM release or early access build. |
| 140 | +For other installation options, visit the [Downloads section](https://www.graalvm.org/downloads/). |
| 141 | + |
| 142 | +1. Build a native executable using Native Build Tools: |
| 143 | + - Maven: |
| 144 | + ```bash |
| 145 | + ./mvnw -Pnative native:compile |
| 146 | + ``` |
| 147 | + The command compiles the project and creates a native executable, `demo`, in the _target/_ directory. |
| 148 | + |
| 149 | + - Gradle: |
| 150 | + ```bash |
| 151 | + ./gradlew nativeCompile |
| 152 | + ``` |
| 153 | + The command compiles the project and creates a native executable, `demo`, in the _build/native/nativeCompile/_ directory. |
| 154 | + |
| 155 | +2. Run the application from the native executable: |
| 156 | + - Maven: |
| 157 | + ```bash |
| 158 | + ./target/demo |
| 159 | + ``` |
| 160 | + - Gradle: |
| 161 | + ```bash |
| 162 | + ./build/native/nativeCompile/demo |
| 163 | + ``` |
| 164 | + With Gradle, you can also execute the `nativeRun` task: `gradle nativeRun`. |
| 165 | + |
| 166 | + If you ran this application on HotSpot before, you would notice that startup time decreased significantly. |
| 167 | + |
| 168 | +This guide demonstrated how you can create a native executable for a Spring Boot application. |
| 169 | +You can do that in a container environment using Paketo Buildpacks, or on a host machine using Native Build Tools. |
| 170 | + |
| 171 | +A Spring Boot application when compiled ahead of time into a native executable is not only faster and lighter, but also more efficient, especially in environments with constrained resources such as cloud platforms or containers. |
| 172 | + |
| 173 | +### Related Documentation |
| 174 | + |
| 175 | +* [Developing Your First GraalVM Native Application](https://docs.spring.io/spring-boot/docs/3.0.0/reference/htmlsingle/#native-image.developing-your-first-application){:target="_blank"} |
| 176 | +* [Paketo Buildpack for Oracle](https://github.com/paketo-buildpacks/oracle){:target="_blank"} |
| 177 | +* [Native Build Tools](https://graalvm.github.io/native-build-tools/latest/index.html){:target="_blank"} |
0 commit comments