Cette page suppose une application Jakarta REST 4.0 déjà fonctionnelle sur Cassini (ou tout autre runtime JAX-RS compatible). Elle décrit l’ajout de Grimm : dépendances, annotation minimale, premier appel GET /openapi.

Prérequis

  • Java 25 (LTS) — Temurin recommandé.

  • Maven 3.9.16 — épinglé par .sdkmanrc à la racine de Grimm.

  • Une application JAX-RS 4.0 déjà déployée, avec au moins une ressource @Path.

sdk env
./mvnw -ntp install -DskipTests

Dépendances Maven

grimm-core contient le scanner et le sérialiseur. grimm-cdi-vauban ajoute la BCE et l’endpoint /openapi. Pour une application standard, déclarer les deux et laisser le runtime brancher le reste.

<dependencies>
    <dependency>
        <groupId>io.vidocq.grimm</groupId>
        <artifactId>grimm-core</artifactId>
        <version>0.1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>io.vidocq.grimm</groupId>
        <artifactId>grimm-cdi-vauban</artifactId>
        <version>0.1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.microprofile.openapi</groupId>
        <artifactId>microprofile-openapi-api</artifactId>
        <version>4.1</version>
    </dependency>
</dependencies>

microprofile-openapi-api est en provided dans grimm-core mais peut être déclaré en compile côté application — c’est lui qui apporte les annotations à utiliser dans le code applicatif.

Annotation racine sur la classe Application

L’annotation @OpenAPIDefinition portée par la classe Application JAX-RS donne le titre, la version et la licence du document.

package io.example;

import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;
import org.eclipse.microprofile.openapi.annotations.OpenAPIDefinition;
import org.eclipse.microprofile.openapi.annotations.info.Info;
import org.eclipse.microprofile.openapi.annotations.info.License;

@ApplicationPath("/api")
@OpenAPIDefinition(
    info = @Info(
        title = "Pet Store API",
        version = "1.0.0",
        license = @License(name = "Apache 2.0", url = "https://www.apache.org/licenses/LICENSE-2.0")
    )
)
public class PetStoreApp extends Application { }

Ressource JAX-RS annotée

Une ressource JAX-RS minimale, complétée par @Operation et @Schema pour décrire l’opération.

package io.example;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;

@Path("/pets")
@ApplicationScoped
public class PetResource {

    @GET
    @Path("/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    @Operation(summary = "Retrouve un animal par identifiant")
    public Pet find(
        @Parameter(description = "Identifiant unique", required = true)
        @PathParam("id") long id) {
        return new Pet(id, "Rex");
    }

    @Schema(name = "Pet", description = "Un animal du registre")
    public record Pet(long id, String name) { }
}

Appeler /openapi

Au démarrage, la BCE GrimmExtension scrute le classpath, fusionne les sources, et publie le document. Aucun code applicatif supplémentaire n’est nécessaire.

# YAML — format par défaut, conforme à la spec MP OpenAPI 4.1 §2.2
curl http://localhost:8080/openapi

# JSON via Accept
curl -H "Accept: application/json" http://localhost:8080/openapi

# JSON via override par query (spec §2.3, prioritaire sur Accept)
curl http://localhost:8080/openapi?format=json

Le résultat YAML ressemble à :

openapi: 3.1.0
info:
  title: Pet Store API
  version: 1.0.0
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0
paths:
  /api/pets/{id}:
    get:
      summary: Retrouve un animal par identifiant
      parameters:
        - name: id
          in: path
          required: true
          description: Identifiant unique
          schema:
            type: integer
            format: int64
      responses:
        "200":
          description: OK
components:
  schemas:
    Pet:
      type: object
      description: Un animal du registre
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string

Trois sources combinables

Grimm fusionne jusqu’à trois sources de vérité :

Source Description Activation

Annotations

Scan des classes @Path du module CDI courant.

Automatique, par défaut.

Document statique

Fichier META-INF/openapi.yaml, .yml ou .json packagé dans le classpath.

Présence du fichier suffit.

OASModelReader

Classe Java qui produit un OpenAPI programmatique.

mp.openapi.model.reader=fqn.ModelReader.

L’ordre de priorité est défini par la spec MP OpenAPI 4.1 : OASModelReader < statique < annotations < OASFilter. Voir Concepts pour le détail.

Étape suivante

  • Cas d’usage — pagination, polymorphisme, sécurité, callbacks.

  • Concepts — modèle OpenAPI, fusion, filtres.

  • Référence — annotations supportées, clés mp.openapi.*.