Skip to content

Commit 734a345

Browse files
cstancufniephaus
authored andcommitted
Update README.
1 parent a8d909c commit 734a345

File tree

1 file changed

+181
-13
lines changed
  • native-image/microservices/micronaut-hello-rest-maven-layered

1 file changed

+181
-13
lines changed
Lines changed: 181 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,192 @@
1-
## Micronaut 4.9.4 Documentation
1+
# Microanut Layered Native Image Demo
22

3-
- [User Guide](https://docs.micronaut.io/4.9.4/guide/index.html)
4-
- [API Reference](https://docs.micronaut.io/4.9.4/api/index.html)
5-
- [Configuration Reference](https://docs.micronaut.io/4.9.4/guide/configurationreference.html)
6-
- [Micronaut Guides](https://guides.micronaut.io/index.html)
7-
---
3+
This example shows how to build a simple [Micronaut](https://micronaut.io/) REST application using the [GraalVM Native Image Layers](https://github.com/oracle/graal/blob/master/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/NativeImageLayers.md) feature.
84

9-
- [Micronaut Maven Plugin documentation](https://micronaut-projects.github.io/micronaut-maven-plugin/latest/)
10-
## Feature maven-enforcer-plugin documentation
5+
## Environment Setup
6+
Point your `JAVA_HOME` to a GraalVM distribution.
7+
Native Image Layers is an experimental feature, for best experience use the latest [GraalVM Early Access Build](https://github.com/graalvm/oracle-graalvm-ea-builds/releases).
8+
```bash
9+
export JAVA_HOME=/path/to/graalvm/ea/build
10+
```
1111

12-
- [https://maven.apache.org/enforcer/maven-enforcer-plugin/](https://maven.apache.org/enforcer/maven-enforcer-plugin/)
12+
## Create The Micronaut Application
1313

14+
We'll start by generating a basic application using the Micronaut CLI.
15+
For more details see the [Micronaut guide](https://guides.micronaut.io/latest/creating-your-first-micronaut-app-maven-java.html).
1416

15-
## Feature serialization-jackson documentation
17+
First we need to install the `mn` tool:
18+
```bash
19+
sdk install micronaut 4.9.4
20+
sdk use micronaut 4.9.4
21+
```
1622

17-
- [Micronaut Serialization Jackson Core documentation](https://micronaut-projects.github.io/micronaut-serialization/latest/guide/)
23+
Now we ca generate the basic app:
24+
```bash
25+
mn create-app example.micronaut.micronaut-hello-rest-maven-layered --build=maven --lang=java --features=graalvm
26+
```
1827

28+
### Add A Custom Controller
1929

20-
## Feature micronaut-aot documentation
30+
We'll add a custom controller to `src/main/java/example/micronaut/HelloController.java`:
31+
```java
32+
package example.micronaut;
2133

22-
- [Micronaut AOT documentation](https://micronaut-projects.github.io/micronaut-aot/latest/guide/)
34+
import io.micronaut.http.MediaType;
35+
import io.micronaut.http.annotation.Controller;
36+
import io.micronaut.http.annotation.Get;
37+
import io.micronaut.http.annotation.Produces;
2338

39+
@Controller("/hello")
40+
public class HelloController {
41+
@Get
42+
@Produces(MediaType.TEXT_PLAIN)
43+
public String hello() {
44+
return "Hello from GraalVM Native Image!";
45+
}
46+
}
47+
```
2448

49+
### Standalone Application
50+
51+
We'll first demonstrate how to build a standalone executable for this simple app.
52+
For this we'll extend the `pom.xml` with a custom profile and configure the native build using the [GraalVM Native Image Maven plugin](https://graalvm.github.io/native-build-tools/latest/maven-plugin.html):
53+
```xml
54+
<profile>
55+
<id>standalone</id>
56+
<build>
57+
<plugins>
58+
<plugin>
59+
<groupId>org.graalvm.buildtools</groupId>
60+
<artifactId>native-maven-plugin</artifactId>
61+
<version>0.10.3</version>
62+
<configuration>
63+
<imageName>standalone-app</imageName>
64+
<mainClass>example.micronaut.Application</mainClass>
65+
</configuration>
66+
</plugin>
67+
</plugins>
68+
</build>
69+
</profile>
70+
```
71+
72+
Using this profile we can now generate the executable:
73+
```bash
74+
./mvnw clean package -Dpackaging=native-image -Pstandalone
75+
```
76+
77+
This will generate an executable file that we can run
78+
```bash
79+
./target/standalone-app
80+
__ __ _ _
81+
| \/ (_) ___ _ __ ___ _ __ __ _ _ _| |_
82+
| |\/| | |/ __| '__/ _ \| '_ \ / _` | | | | __|
83+
| | | | | (__| | | (_) | | | | (_| | |_| | |_
84+
|_| |_|_|\___|_| \___/|_| |_|\__,_|\__,_|\__|
85+
12:20:53.437 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 6ms. Server Running: http://localhost:8080
86+
```
87+
and test our custom endpoint
88+
```bash
89+
curl localhost:8080/hello
90+
Hello from GraalVM Native Image!
91+
```
92+
93+
### Layered Application
94+
95+
#### Configure The Base Layer
96+
97+
We will create a base layer that contains both `java.base` and the Micronaut framework.
98+
For this we'll add a second custom profile:
99+
```xml
100+
<profile>
101+
<id>base-layer</id>
102+
<build>
103+
<directory>${project.basedir}/base-layer-target</directory>
104+
<plugins>
105+
<plugin>
106+
<groupId>org.graalvm.buildtools</groupId>
107+
<artifactId>native-maven-plugin</artifactId>
108+
<version>0.10.3</version>
109+
<configuration>
110+
<imageName>libmicronautbaselayer</imageName>
111+
<mainClass>.</mainClass>
112+
<buildArgs>
113+
<buildArg>-H:+UnlockExperimentalVMOptions</buildArg>
114+
<buildArg>-H:LayerCreate=base-layer.nil,module=java.base,package=io.micronaut.*,package=io.netty.*,package=jakarta.*,package=com.fasterxml.jackson.*,package=org.slf4j.*,package=reactor.*,package=org.reactivestreams.*</buildArg>
115+
<buildArg>-H:ApplicationLayerOnlySingletons=io.micronaut.core.io.service.ServiceScanner$StaticServiceDefinitions</buildArg>
116+
<buildArg>-H:ApplicationLayerInitializedClasses=io.micronaut.inject.annotation.AnnotationMetadataSupport</buildArg>
117+
<buildArg>-H:ApplicationLayerInitializedClasses=io.micronaut.core.io.service.MicronautMetaServiceLoaderUtils</buildArg>
118+
<buildArg>-H:-UnlockExperimentalVMOptions</buildArg>
119+
</buildArgs>
120+
</configuration>
121+
</plugin>
122+
</plugins>
123+
</build>
124+
</profile>
125+
```
126+
127+
We use `-H:LayerCreate=` to specify what should be included in the base layer: `java.base`, `io.micronaut`, `io.netty` and a few more other packages that a Micronaut application usually depends on.
128+
For more details consult the [Native Image Layers documentation](https://github.com/oracle/graal/blob/master/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/NativeImageLayers.md).
129+
130+
Additionally we use two options that are specific for layered builds: `-H:ApplicationLayerOnlySingletons=`, which specifies that a singleton object should be installed in the application layer only, and `-H:ApplicationLayerInitializedClasses=`, which registers a class as being initialized in the app layer.
131+
These are necessary for correctly building the Micronaut framework in a layered set-up.
132+
133+
Now we can build the base layer:
134+
```bash
135+
./mvnw clean install -Dpackaging=native-image -Pbase-layer
136+
```
137+
This will create the `base-layer.nil` which is a build time dependency for the application build.
138+
It will also create the `libmicronautbaselayer.so` shared library which is a run time dependency for the application layer.
139+
Note also that we use `install` instead of `package` to ensure that the base layer jar is installed in the `.m2` cache as it will be needed by the application build later.
140+
141+
142+
### Configure The Application Layer
143+
144+
To configure the app layer we'll add an additional profile:
145+
```xml
146+
<profile>
147+
<id>app-layer</id>
148+
<build>
149+
<directory>${project.basedir}/app-layer-target</directory>
150+
<plugins>
151+
<plugin>
152+
<groupId>org.graalvm.buildtools</groupId>
153+
<artifactId>native-maven-plugin</artifactId>
154+
<version>0.10.3</version>
155+
<configuration>
156+
<imageName>layered-app</imageName>
157+
<mainClass>example.micronaut.Application</mainClass>
158+
<buildArgs>
159+
<buildArg>-H:+UnlockExperimentalVMOptions</buildArg>
160+
<buildArg>-H:LayerUse=base-layer-target/base-layer.nil</buildArg>
161+
<buildArg>-H:LinkerRPath=$ORIGIN</buildArg>
162+
<buildArg>-H:-UnlockExperimentalVMOptions</buildArg>
163+
</buildArgs>
164+
</configuration>
165+
</plugin>
166+
</plugins>
167+
</build>
168+
</profile>
169+
```
170+
171+
Now we can build a layered Native Image which depends on the base layer that we created earlier:
172+
```bash
173+
./mvnw clean package -Dpackaging=native-image -Papp-layer
174+
```
175+
176+
This will generate the layered executable file in `./app-layer-target/layered-app` and will copy `libmicronautbaselayer.so` next to it.
177+
178+
Then we can execute the layered application:
179+
```bash
180+
./app-layer-target/layered-app
181+
__ __ _ _
182+
| \/ (_) ___ _ __ ___ _ __ __ _ _ _| |_
183+
| |\/| | |/ __| '__/ _ \| '_ \ / _` | | | | __|
184+
| | | | | (__| | | (_) | | | | (_| | |_| | |_
185+
|_| |_|_|\___|_| \___/|_| |_|\__,_|\__,_|\__|
186+
12:24:21.341 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 6ms. Server Running: http://localhost:8080
187+
```
188+
and test it with:
189+
```
190+
curl localhost:8080/hello
191+
Hello from GraalVM Native Image!
192+
```

0 commit comments

Comments
 (0)