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}]

Next steps