This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch CAMEL-25765-rest-code-first
in repository https://gitbox.apache.org/repos/asf/camel-jbang-examples.git

commit 0d19f7e5c9b5ef526bbf88cd7a16d36923d07fbd
Author: Claus Ibsen <[email protected]>
AuthorDate: Sun Oct 18 15:12:26 2026 +0200

    CAMEL-25765: contracts/rest-code-first - the REST DSL with JSON binding to 
a Java record and a generated API description
    
    GET /orders and GET /orders/{id} answer the orders as JSON through the json
    binding, POST /orders binds a new order to a Java record and answers 201,
    400 without lines, and the generated API description is served at
    /openapi. First in the contracts group, before the contract-first
    examples, with a Citrus YAML test in the CI matrix.
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
    Claude-Session: https://claude.ai/code/session_01STT6whBgK1AqsSsUKrnE8m
---
 .github/workflows/build.yml                        |   2 +
 README.md                                          |   1 +
 camel-jbang-example-catalog.json                   |  52 +++++++++-
 contracts/README.md                                |   3 +-
 contracts/keycloak-security-rest/metadata.json     |   2 +-
 contracts/openapi-client/metadata.json             |   2 +-
 contracts/openapi-server/metadata.json             |   2 +-
 contracts/rest-code-first/Order.java               |  30 ++++++
 contracts/rest-code-first/README.md                |  91 ++++++++++++++++++
 contracts/rest-code-first/application.properties   |  20 ++++
 contracts/rest-code-first/metadata.json            |  38 ++++++++
 contracts/rest-code-first/orders.json              |   5 +
 .../rest-code-first/rest-code-first.camel.yaml     | 107 +++++++++++++++++++++
 .../test/rest-code-first.citrus.it.yaml            |  95 ++++++++++++++++++
 14 files changed, 444 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 05cc0cd..8251be4 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -86,6 +86,8 @@ jobs:
             path: connect/file-processing
           - name: MCP server
             path: ai/mcp-server
+          - name: REST code first
+            path: contracts/rest-code-first
           - name: OpenAPI server
             path: contracts/openapi-server
           - name: OpenAPI client
diff --git a/README.md b/README.md
index 290139b..e13e217 100644
--- a/README.md
+++ b/README.md
@@ -114,6 +114,7 @@ An OpenAPI contract served and called, and an API protected 
by Keycloak.
 
 | Example | What you will see | Needs |
 |---|---|---|
+| [REST code first](contracts/rest-code-first/) | The shop's order API written 
with the REST DSL: GET /orders and GET /orders/{id} answer the orders as JSON 
(404 for an unknown id), POST /orders binds the JSON of a new order to a Java 
record and answers 201 (400 without lines), and the API description generated 
from the operations is served at /openapi. | nothing |
 | [OpenAPI server](contracts/openapi-server/) | The stock API contract first: 
stock-api.json is the OpenAPI contract, the REST DSL serves its three 
operations on port 8080 with request validation, GET /stock/{sku} answers from 
a file or 404, POST /stock/{sku}/reserve answers 200, 409 when the stock is 
short or 400 for a bad reservation, and /openapi serves the contract. | nothing 
|
 | [OpenAPI client](contracts/openapi-client/) | The picking desk reserves 
stock for every order line by calling the stock API by contract: rest-openapi 
turns the operationId reserveStock into the HTTP call from stock-api.json; the 
log shows each reservation and one 409 for the cap that is out of stock. Needs 
the openapi-server example running. | `contracts/openapi-server` running first |
 | [Keycloak security](contracts/keycloak-security-rest/) | Two HTTP endpoints 
on port 8081: the public one answers everyone, the protected one requires a 
bearer token from a Keycloak started with camel infra whose user has the admin 
role, otherwise 403; the realm, client and users are created in the Keycloak 
console as the README describes. | `camel infra run keycloak` |
diff --git a/camel-jbang-example-catalog.json b/camel-jbang-example-catalog.json
index 0be9e36..789b311 100644
--- a/camel-jbang-example-catalog.json
+++ b/camel-jbang-example-catalog.json
@@ -657,7 +657,7 @@
         "infraServices": [
             "keycloak"
         ],
-        "order": 3
+        "order": 4
     },
     {
         "name": "contracts/openapi-client",
@@ -705,7 +705,7 @@
             "stock-api.json"
         ],
         "needs": "`contracts/openapi-server` running first",
-        "order": 2
+        "order": 3
     },
     {
         "name": "contracts/openapi-server",
@@ -753,6 +753,54 @@
             "stock-api.json",
             "stock.json"
         ],
+        "order": 2
+    },
+    {
+        "name": "contracts/rest-code-first",
+        "title": "REST code first",
+        "description": "The shop's order API written with the REST DSL: GET 
/orders and GET /orders/{id} answer the orders as JSON (404 for an unknown id), 
POST /orders binds the JSON of a new order to a Java record and answers 201 
(400 without lines), and the API description generated from the operations is 
served at /openapi.",
+        "level": "contracts",
+        "teaches": {
+            "components": [
+                "rest",
+                "platform-http",
+                "direct",
+                "log"
+            ],
+            "eips": [
+                "restConfiguration",
+                "rest",
+                "choice",
+                "filter",
+                "setHeader",
+                "unmarshal"
+            ],
+            "languages": [
+                "simple",
+                "groovy"
+            ],
+            "dataformats": [
+                "json"
+            ]
+        },
+        "tags": [
+            "shop",
+            "rest",
+            "code-first",
+            "binding",
+            "openapi",
+            "java-record"
+        ],
+        "bundled": true,
+        "requiresDocker": false,
+        "hasCitrusTests": true,
+        "files": [
+            "Order.java",
+            "README.md",
+            "application.properties",
+            "orders.json",
+            "rest-code-first.camel.yaml"
+        ],
         "order": 1
     },
     {
diff --git a/contracts/README.md b/contracts/README.md
index e1b5d8b..e3803e4 100644
--- a/contracts/README.md
+++ b/contracts/README.md
@@ -5,11 +5,12 @@ An OpenAPI contract served and called, and an API protected 
by Keycloak.
 
 | Example | What you will see | Needs |
 |---|---|---|
+| [REST code first](rest-code-first/) | The shop's order API written with the 
REST DSL: GET /orders and GET /orders/{id} answer the orders as JSON (404 for 
an unknown id), POST /orders binds the JSON of a new order to a Java record and 
answers 201 (400 without lines), and the API description generated from the 
operations is served at /openapi. | nothing |
 | [OpenAPI server](openapi-server/) | The stock API contract first: 
stock-api.json is the OpenAPI contract, the REST DSL serves its three 
operations on port 8080 with request validation, GET /stock/{sku} answers from 
a file or 404, POST /stock/{sku}/reserve answers 200, 409 when the stock is 
short or 400 for a bad reservation, and /openapi serves the contract. | nothing 
|
 | [OpenAPI client](openapi-client/) | The picking desk reserves stock for 
every order line by calling the stock API by contract: rest-openapi turns the 
operationId reserveStock into the HTTP call from stock-api.json; the log shows 
each reservation and one 409 for the cap that is out of stock. Needs the 
openapi-server example running. | `contracts/openapi-server` running first |
 | [Keycloak security](keycloak-security-rest/) | Two HTTP endpoints on port 
8081: the public one answers everyone, the protected one requires a bearer 
token from a Keycloak started with camel infra whose user has the admin role, 
otherwise 403; the realm, client and users are created in the Keycloak console 
as the README describes. | `camel infra run keycloak` |
 
-Start with [OpenAPI server](openapi-server/); the examples read best in the 
order above, each one building on what the one before it set up.
+Start with [REST code first](rest-code-first/); the examples read best in the 
order above, each one building on what the one before it set up.
 
 Every example has a README that says what you will see, how it works, how to 
build it step by step and what to try changing; the ones with a `test/` 
directory also say how to run their test with `camel test run`.
 <!-- group:end -->
diff --git a/contracts/keycloak-security-rest/metadata.json 
b/contracts/keycloak-security-rest/metadata.json
index 9c54063..d0b2474 100644
--- a/contracts/keycloak-security-rest/metadata.json
+++ b/contracts/keycloak-security-rest/metadata.json
@@ -2,7 +2,7 @@
     "title": "Keycloak security",
     "description": "Two HTTP endpoints on port 8081: the public one answers 
everyone, the protected one requires a bearer token from a Keycloak started 
with camel infra whose user has the admin role, otherwise 403; the realm, 
client and users are created in the Keycloak console as the README describes.",
     "level": "contracts",
-    "order": 3,
+    "order": 4,
     "teaches": {
         "components": [
             "platform-http",
diff --git a/contracts/openapi-client/metadata.json 
b/contracts/openapi-client/metadata.json
index 588b520..1cb29e6 100644
--- a/contracts/openapi-client/metadata.json
+++ b/contracts/openapi-client/metadata.json
@@ -2,7 +2,7 @@
     "title": "OpenAPI client",
     "description": "The picking desk reserves stock for every order line by 
calling the stock API by contract: rest-openapi turns the operationId 
reserveStock into the HTTP call from stock-api.json; the log shows each 
reservation and one 409 for the cap that is out of stock. Needs the 
openapi-server example running.",
     "level": "contracts",
-    "order": 2,
+    "order": 3,
     "teaches": {
         "components": [
             "rest-openapi",
diff --git a/contracts/openapi-server/metadata.json 
b/contracts/openapi-server/metadata.json
index 20456f6..2d9037f 100644
--- a/contracts/openapi-server/metadata.json
+++ b/contracts/openapi-server/metadata.json
@@ -2,7 +2,7 @@
     "title": "OpenAPI server",
     "description": "The stock API contract first: stock-api.json is the 
OpenAPI contract, the REST DSL serves its three operations on port 8080 with 
request validation, GET /stock/{sku} answers from a file or 404, POST 
/stock/{sku}/reserve answers 200, 409 when the stock is short or 400 for a bad 
reservation, and /openapi serves the contract.",
     "level": "contracts",
-    "order": 1,
+    "order": 2,
     "teaches": {
         "components": [
             "rest",
diff --git a/contracts/rest-code-first/Order.java 
b/contracts/rest-code-first/Order.java
new file mode 100644
index 0000000..cc39359
--- /dev/null
+++ b/contracts/rest-code-first/Order.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package camel.example;
+
+import java.util.List;
+
+/**
+ * An order of the shop, as the JSON of POST /orders binds to it: the REST DSL 
turns the request body into this record
+ * (bindingMode json, type camel.example.Order), and the record back into JSON 
for the answer.
+ */
+public record Order(String orderId, String customer, String country, String 
status, List<Line> lines) {
+
+    /** One line of an order. */
+    public record Line(String sku, int qty, double price) {
+    }
+}
diff --git a/contracts/rest-code-first/README.md 
b/contracts/rest-code-first/README.md
new file mode 100644
index 0000000..fe96d6c
--- /dev/null
+++ b/contracts/rest-code-first/README.md
@@ -0,0 +1,91 @@
+# REST code first
+
+The shop's order API written with the REST DSL. The routes declare each 
operation, the JSON of a new order is bound
+to a Java record, and Camel builds the API description from the operations and 
serves it at `/openapi`.
+
+## What you will see
+
+```text
+INFO ... rest-code-first.camel.yaml:101 : Order ORD-1004 created with 1 line(s)
+```
+
+and the answers of the API:
+
+```shell
+$ curl http://localhost:8080/orders/ORD-1002
+{"orderId":"ORD-1002","customer":"C-207","country":"DE","status":"paid","lines":[{"sku":"CAMEL-MUG","qty":3,"price":9.5}]}
+
+$ curl -i http://localhost:8080/orders/ORD-9999
+HTTP/1.1 404 Not Found
+{"error": "unknown order ORD-9999"}
+
+$ curl -i -H 'Content-Type: application/json' -d '{"orderId": "ORD-1004", 
"customer": "C-482", "country": "DK", "status": "paid", "lines": [{"sku": 
"CAMEL-MUG", "qty": 1, "price": 9.5}]}' http://localhost:8080/orders
+HTTP/1.1 201 Created
+{"orderId":"ORD-1004","customer":"C-482","country":"DK","status":"paid","lines":[{"sku":"CAMEL-MUG","qty":1,"price":9.5}]}
+```
+
+## Install Camel CLI
+
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
+
+## Run it
+
+```shell
+camel run *
+```
+
+Then call the API as shown above. `curl http://localhost:8080/openapi` shows 
the API description.
+Stop the example with `ctrl` + `c`.
+
+## How it works
+
+- `rest-code-first.camel.yaml` declares the API with the REST DSL: `GET 
/orders`, `GET /orders/{id}` and
+  `POST /orders`, each with an id and a description, and each sent to a 
`direct` route.
+- `restConfiguration` sets `bindingMode: json`. The answers are Java objects 
(a List, a Map, a record), and the
+  binding writes them as JSON. For `POST /orders`, `type: camel.example.Order` 
makes the binding read the request
+  JSON into the record.
+- `Order.java` is the record, with a nested record per line. Simple reads its 
fields as `${body.orderId}`.
+- An error answer, 404 or 400, is not bound (`skipBindingOnErrorCode` is on by 
default), so the route writes it as
+  JSON text.
+- `apiContextPath: openapi` serves the API description that Camel generates 
from the operations.
+  `application.properties` adds `camel-openapi-java` for it, which `camel run` 
does not add by itself for a
+  code-first API.
+- `orders.json` holds the three orders of the shop.
+
+## Build it step by step
+
+Ask your assistant, or type it yourself, one step at a time, and run after 
each:
+
+1. A REST DSL `GET /orders` that answers the orders from `orders.json`.
+2. `GET /orders/{id}`: the order with that id, or 404 with `{"error": "unknown 
order <id>"}`.
+3. `POST /orders` with JSON binding to a Java record `camel.example.Order`: 
400 when the order has no lines,
+   otherwise log the order and answer 201.
+4. Serve the API description at `/openapi`.
+
+## Try changing
+
+- `bindingMode: off`: the answers are no longer JSON, and the routes have to 
marshal them themselves.
+- Add `PUT /orders/{id}` that changes the status of an order.
+- Compare with the [openapi-server](../openapi-server/) example, which starts 
from the contract instead.
+
+## Integration testing
+
+The example comes with a test in the [Citrus](https://citrusframework.org/) 
YAML DSL,
+`test/rest-code-first.citrus.it.yaml`, which the Camel CLI runs:
+
+```shell
+camel test run test/rest-code-first.citrus.it.yaml
+```
+
+The test calls each operation and checks the answers, and the API description.
+
+## Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+[let us know](https://camel.apache.org/community/support/).
+
+We also love contributors, so
+[get involved](https://camel.apache.org/community/contributing/) :-)
+
+The Camel riders!
diff --git a/contracts/rest-code-first/application.properties 
b/contracts/rest-code-first/application.properties
new file mode 100644
index 0000000..ee269d6
--- /dev/null
+++ b/contracts/rest-code-first/application.properties
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+camel.server.port=8080
+# the API description at /openapi needs camel-openapi-java, which camel run 
does not add by itself for code-first REST
+camel.jbang.dependencies=camel:openapi-java
diff --git a/contracts/rest-code-first/metadata.json 
b/contracts/rest-code-first/metadata.json
new file mode 100644
index 0000000..111cc1a
--- /dev/null
+++ b/contracts/rest-code-first/metadata.json
@@ -0,0 +1,38 @@
+{
+    "title": "REST code first",
+    "description": "The shop's order API written with the REST DSL: GET 
/orders and GET /orders/{id} answer the orders as JSON (404 for an unknown id), 
POST /orders binds the JSON of a new order to a Java record and answers 201 
(400 without lines), and the API description generated from the operations is 
served at /openapi.",
+    "level": "contracts",
+    "order": 1,
+    "teaches": {
+        "components": [
+            "rest",
+            "platform-http",
+            "direct",
+            "log"
+        ],
+        "eips": [
+            "restConfiguration",
+            "rest",
+            "choice",
+            "filter",
+            "setHeader",
+            "unmarshal"
+        ],
+        "languages": [
+            "simple",
+            "groovy"
+        ],
+        "dataformats": [
+            "json"
+        ]
+    },
+    "tags": [
+        "shop",
+        "rest",
+        "code-first",
+        "binding",
+        "openapi",
+        "java-record"
+    ],
+    "bundled": true
+}
diff --git a/contracts/rest-code-first/orders.json 
b/contracts/rest-code-first/orders.json
new file mode 100644
index 0000000..ceea517
--- /dev/null
+++ b/contracts/rest-code-first/orders.json
@@ -0,0 +1,5 @@
+[
+  {"orderId": "ORD-1001", "customer": "C-482", "country": "DK", "status": 
"paid", "lines": [{"sku": "CAMEL-TSHIRT", "qty": 2, "price": 19.95}, {"sku": 
"CAMEL-MUG", "qty": 1, "price": 9.5}]},
+  {"orderId": "ORD-1002", "customer": "C-207", "country": "DE", "status": 
"paid", "lines": [{"sku": "CAMEL-MUG", "qty": 3, "price": 9.5}]},
+  {"orderId": "ORD-1003", "customer": "C-134", "country": "US", "status": 
"pending", "lines": [{"sku": "CAMEL-TSHIRT", "qty": 1, "price": 19.95}, {"sku": 
"CAMEL-CAP", "qty": 1, "price": 14.0}, {"sku": "CAMEL-MUG", "qty": 2, "price": 
9.5}]}
+]
diff --git a/contracts/rest-code-first/rest-code-first.camel.yaml 
b/contracts/rest-code-first/rest-code-first.camel.yaml
new file mode 100644
index 0000000..186bbd7
--- /dev/null
+++ b/contracts/rest-code-first/rest-code-first.camel.yaml
@@ -0,0 +1,107 @@
+# The shop's order API, code first: the REST DSL declares each operation, 
binds the JSON of a new order to a Java
+# record, and builds the API description from the operations, served at 
/openapi.
+- restConfiguration:
+    bindingMode: json
+    apiContextPath: openapi
+
+- rest:
+    path: /orders
+    get:
+      - id: listOrders
+        description: All orders
+        to:
+          uri: direct:list-orders
+      - id: getOrder
+        path: "/{id}"
+        description: One order, by its id
+        to:
+          uri: direct:get-order
+    post:
+      - id: createOrder
+        description: Creates an order
+        type: camel.example.Order
+        to:
+          uri: direct:create-order
+
+# The answers are Java objects (a List, a Map, a record): the json binding 
writes them as JSON
+- route:
+    id: list-orders
+    from:
+      uri: direct
+      parameters:
+        name: list-orders
+      steps:
+        - setBody:
+            expression:
+              constant:
+                expression: "resource:file:orders.json"
+        - unmarshal:
+            json:
+              library: Jackson
+
+- route:
+    id: get-order
+    from:
+      uri: direct
+      parameters:
+        name: get-order
+      steps:
+        - setBody:
+            expression:
+              constant:
+                expression: "resource:file:orders.json"
+        - unmarshal:
+            json:
+              library: Jackson
+        - setBody:
+            expression:
+              groovy:
+                expression: "body.find { it.orderId == headers.id }"
+        - filter:
+            expression:
+              simple:
+                expression: "${body} == null"
+            steps:
+              - setHeader:
+                  name: CamelHttpResponseCode
+                  expression:
+                    constant:
+                      expression: "404"
+              # an error answer is not bound to JSON (skipBindingOnErrorCode), 
so it is written as JSON text
+              - setBody:
+                  expression:
+                    simple:
+                      expression: '{"error": "unknown order ${header.id}"}'
+
+# The binding has turned the request into a camel.example.Order record
+- route:
+    id: create-order
+    from:
+      uri: direct
+      parameters:
+        name: create-order
+      steps:
+        - choice:
+            when:
+              - expression:
+                  simple:
+                    expression: "${body.lines} == null || 
${body.lines.isEmpty()}"
+                steps:
+                  - setHeader:
+                      name: CamelHttpResponseCode
+                      expression:
+                        constant:
+                          expression: "400"
+                  - setBody:
+                      expression:
+                        constant:
+                          expression: '{"error": "an order needs at least one 
line"}'
+            otherwise:
+              steps:
+                - log:
+                    message: "Order ${body.orderId} created with 
${body.lines.size()} line(s)"
+                - setHeader:
+                    name: CamelHttpResponseCode
+                    expression:
+                      constant:
+                        expression: "201"
diff --git a/contracts/rest-code-first/test/rest-code-first.citrus.it.yaml 
b/contracts/rest-code-first/test/rest-code-first.citrus.it.yaml
new file mode 100644
index 0000000..b1d7cb2
--- /dev/null
+++ b/contracts/rest-code-first/test/rest-code-first.citrus.it.yaml
@@ -0,0 +1,95 @@
+name: rest-code-first-test
+description: The order API answers as the README shows
+actions:
+  - camel:
+      jbang:
+        run:
+          integration:
+            name: "rest-code-first"
+            file: "../rest-code-first.camel.yaml"
+            systemProperties:
+              file: "../application.properties"
+          resources:
+            - "Order.java"
+            - "orders.json"
+  - camel:
+      jbang:
+        verify:
+          integration: "rest-code-first"
+          logMessage: "(rest-code-first) started"
+  - http:
+      client: "http://localhost:8080";
+      sendRequest:
+        GET:
+          path: "/orders/ORD-1002"
+          # the client's default Content-Type text/plain makes the json 
binding skip writing the answer
+          contentType: "application/json"
+  - http:
+      client: "http://localhost:8080";
+      receiveResponse:
+        response:
+          status: "200"
+        validate:
+          - jsonPath:
+              - expression: "$.customer"
+                value: "C-207"
+  - http:
+      client: "http://localhost:8080";
+      sendRequest:
+        GET:
+          path: "/orders/ORD-9999"
+          # the client's default Content-Type text/plain makes the json 
binding skip writing the answer
+          contentType: "application/json"
+  - http:
+      client: "http://localhost:8080";
+      receiveResponse:
+        response:
+          status: "404"
+        validate:
+          - jsonPath:
+              - expression: "$.error"
+                value: "unknown order ORD-9999"
+  - http:
+      client: "http://localhost:8080";
+      sendRequest:
+        POST:
+          path: "/orders"
+          contentType: "application/json"
+          body:
+            data: '{"orderId": "ORD-1004", "customer": "C-482", "country": 
"DK", "status": "paid", "lines": [{"sku": "CAMEL-MUG", "qty": 1, "price": 
9.5}]}'
+  - http:
+      client: "http://localhost:8080";
+      receiveResponse:
+        response:
+          status: "201"
+        validate:
+          - jsonPath:
+              - expression: "$.orderId"
+                value: "ORD-1004"
+  - http:
+      client: "http://localhost:8080";
+      sendRequest:
+        POST:
+          path: "/orders"
+          contentType: "application/json"
+          body:
+            data: '{"orderId": "ORD-1005", "customer": "C-482", "country": 
"DK", "status": "paid", "lines": []}'
+  - http:
+      client: "http://localhost:8080";
+      receiveResponse:
+        response:
+          status: "400"
+  - http:
+      client: "http://localhost:8080";
+      sendRequest:
+        GET:
+          path: "/openapi"
+  - http:
+      client: "http://localhost:8080";
+      receiveResponse:
+        response:
+          status: "200"
+        validate:
+          - jsonPath:
+              - expression: "$.paths['/orders/{id}'].get.operationId"
+                value: "getOrder"

Reply via email to