This page boots a complete REST + DI + H2 persistence service with Vidocq Runtime, packages the application via the dedicated Maven plugin, and runs it with java -jar. The example mirrors vidocq-runtime-mansart-h2-example from the reactor.
Prerequisites
-
Java 25 (Temurin recommended)
-
Maven 3.9.16 — pinned via
.sdkmanrc(sdk env) -
Basic knowledge of Jakarta REST, CDI Lite and MicroProfile Config
Maven coordinates
<dependencies>
<dependency>
<groupId>io.vidocq.runtime</groupId>
<artifactId>vidocq-runtime-core</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.vidocq.runtime</groupId>
<artifactId>vidocq-runtime-cassini-rest-extension</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.vidocq.runtime</groupId>
<artifactId>vidocq-runtime-mansart-extension</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.x</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.vidocq.runtime</groupId>
<artifactId>vidocq-runtime-maven-plugin</artifactId>
<version>0.1.0-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>jlink</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Step 1 — An entity and a repository
package io.example.todo;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity
public class Todo {
@Id @GeneratedValue Long id;
String label;
boolean done;
// accessors
}
package io.example.todo;
import jakarta.data.repository.CrudRepository;
import jakarta.data.repository.Repository;
@Repository
public interface TodoRepository extends CrudRepository<Todo, Long> {}
Mansart generates the implementation via APT at build time. No runtime class is reflectively instantiated.
Step 2 — A REST resource
package io.example.todo;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
@Path("/api/todos")
@ApplicationScoped
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class TodoResource {
@Inject TodoRepository repo;
@GET
public Iterable<Todo> list() {
return repo.findAll();
}
@POST
public Todo create(Todo input) {
return repo.save(input);
}
}
The @RequestScoped scope is added automatically by the RestScopeExtension Build Compatible Extension on the Vauban side.
Step 3 — Entry point
package io.example.todo;
public class App {
public static void main(String[] args) {
io.vidocq.runtime.Vidocq.main(args);
}
}
Vidocq.main(args) orchestrates the full boot sequence. See Internals.
Step 4 — MicroProfile configuration
src/main/resources/vidocq.properties:
# transport (Chappe)
vidocq.http.host=0.0.0.0
vidocq.http.port=8080
# datasource (Mansart)
vidocq.datasource.url=jdbc:h2:mem:todo
vidocq.datasource.username=sa
vidocq.datasource.password=
Any key is overridable via -Dkey=value, environment variables, or an external file (see Usage).
Step 5 — Build and run
sdk env
./mvnw -ntp package -DskipTests
java -jar target/quickstart-runner.jar
# or in jlink mode (standalone image — no java required):
./target/dist/bin/quickstart
$ curl -X POST http://localhost:8080/api/todos \
-H 'Content-Type: application/json' \
-d '{"label":"write docs","done":false}'
$ curl http://localhost:8080/api/todos
[{"id":1,"label":"write docs","done":false}]