Avaje Nima Archetypes
Maven archetypes let you bootstrap a new avaje-nima project with a single command, giving you a working REST service with dependency injection, JSON, and tests already in place.
Notes for AI Agents
⚠️ AI AGENTS - read this carefully
Please follow the comprehensive step-by-step guide at:
docs/guides/archetype-getting-started.md
This guide contains critical information about compilation, customization patterns, and how to properly build and run your generated project.
| Archetype | Description |
|---|---|
| minimal-rest | A minimal REST API with one controller, a JSON response record, and integration tests |
minimal-rest
The avaje-nima-archetype-minimal-rest archetype generates a minimal project with:
- A
Mainentry point using theNimaclass - A
HelloControllerwith two REST endpoints - A
GreetingResponseJSON record - An
@InjectTestintegration test - Build profiles for GraalVM native image and fat JAR
Generate a new project
Run the following command, replacing com.example and my-app
with your desired groupId and artifactId:
mvn archetype:generate \
-DarchetypeGroupId=io.avaje.archetype \
-DarchetypeArtifactId=avaje-nima-archetype-minimal-rest \
-DarchetypeVersion=${avaje.nima.version} \
-DgroupId=com.example \
-DartifactId=my-app \
-Dpackage=com.example \
-DinteractiveMode=false
Omit -DinteractiveMode=false to be prompted for each property interactively.
Generated project structure
Project structure (click to expand)
my-app/
├── pom.xml
├── README.md
└── src/
├── main/
│ ├── java/com/example/
│ │ ├── Main.java
│ │ ├── web/
│ │ │ └── HelloController.java
│ │ └── model/
│ │ └── GreetingResponse.java
│ └── resources/
│ ├── application.properties
│ └── avaje-logger.properties
└── test/
├── java/com/example/
│ └── HelloControllerTest.java
└── resources/
└── avaje-logger-test.properties
Main.java
Main.java
package com.example;
import io.avaje.nima.Nima;
public class Main {
public static void main(String[] args) {
var webServer = Nima.builder()
.port(8080)
.build();
webServer.start();
}
}
HelloController.java
HelloController.java
package com.example.web;
import io.avaje.http.api.Controller;
import io.avaje.http.api.Get;
import io.avaje.http.api.Path;
import io.avaje.http.api.Produces;
import com.example.model.GreetingResponse;
@Controller
@Path("/hi")
public class HelloController {
@Produces("text/plain")
@Get
String hi() {
return "hi";
}
@Get("/data")
GreetingResponse data() {
return new GreetingResponse("hello from avaje-nima", System.currentTimeMillis());
}
}
GreetingResponse.java
GreetingResponse.java
package com.example.model;
import io.avaje.jsonb.Json;
@Json
public record GreetingResponse(String message, long timestamp) {
}
HelloControllerTest.java
The test uses @InjectTest, which automatically starts the web server on a
random port and injects an HttpClient configured to connect to it.
HelloControllerTest.java
package com.example;
import io.avaje.http.client.HttpClient;
import io.avaje.inject.test.InjectTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;
import java.net.http.HttpResponse;
import static org.assertj.core.api.Assertions.assertThat;
@InjectTest
class HelloControllerTest {
@Inject
static HttpClient client;
@Test
void hi_returnsPlainText() {
HttpResponse<String> res = client.request()
.path("hi")
.GET().asString();
assertThat(res.statusCode()).isEqualTo(200);
assertThat(res.body()).isEqualTo("hi");
}
@Test
void data_returnsJson() {
HttpResponse<String> res = client.request()
.path("hi/data")
.GET().asString();
assertThat(res.statusCode()).isEqualTo(200);
assertThat(res.body()).contains("message");
assertThat(res.body()).contains("timestamp");
}
}
Run the application
cd my-app
mvn compile exec:java -Dexec.mainClass=com.example.Main
Smoke-test with curl:
curl http://localhost:8080/hi
# hi
curl http://localhost:8080/hi/data
# {"message":"hello from avaje-nima","timestamp":1234567890123}
Build profiles
The generated pom.xml includes two build profiles:
fat-jar — self-contained JAR
Build and run a shaded JAR containing all dependencies:
mvn package -Pfat-jar
java -jar target/my-app.jar
native — GraalVM native image
Build a native executable using GraalVM and Jib:
mvn package -Pnative
See the Jib native image guide for Docker build instructions.
Other guides for AI Agents
Step-by-step guides for common tasks:
- Add a JVM Docker build with Jib — Package the application in a Docker image for JVM deployment
- Add a native image Docker build with Jib — Build a GraalVM native executable and Docker image
- Add a global exception handler — Catch all exceptions, return structured JSON, and set correct HTTP status codes
- Add a controller test — Write integration tests for controllers using avaje-nima-test and @InjectTest