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

cdeppisch pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-jbang-examples.git


The following commit(s) were added to refs/heads/main by this push:
     new d25b121  fix(#6): Add Open API server example
d25b121 is described below

commit d25b121fa1daf949a26cbf5ecfc0acead9c1ef75
Author: Christoph Deppisch <[email protected]>
AuthorDate: Thu Jan 9 16:59:40 2025 +0100

    fix(#6): Add Open API server example
---
 .github/workflows/build.yml                |   4 +
 openapi/server/README.adoc                 |  79 ++++++++
 openapi/server/application.properties      |  19 ++
 openapi/server/examples/pet/1000.json      |  18 ++
 openapi/server/petstore-api.json           | 299 +++++++++++++++++++++++++++++
 openapi/server/petstore.camel.yaml         |   6 +
 openapi/server/test/examples/pet/1000.json |  18 ++
 openapi/server/test/jbang.properties       |   2 +
 openapi/server/test/petstore-api.json      | 299 +++++++++++++++++++++++++++++
 openapi/server/test/petstore.camel.it.yaml |  27 +++
 10 files changed, 771 insertions(+)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 3343cb9..740b616 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -66,6 +66,10 @@ jobs:
           pushd mqtt/test
           jbang citrus@citrusframework/citrus run mqtt.camel.it.yaml
           popd
+          
+          pushd openapi/server/test
+          jbang citrus@citrusframework/citrus run petstore.camel.it.yaml
+          popd
       - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 
# v4.4.0
         if: always()
         with:
diff --git a/openapi/server/README.adoc b/openapi/server/README.adoc
new file mode 100644
index 0000000..82bc120
--- /dev/null
+++ b/openapi/server/README.adoc
@@ -0,0 +1,79 @@
+= Open API server
+
+This example uses an Open API specification as a base for creating a REST 
service in Camel.
+The Camel route is configured to implement the operations declared in the Open 
API specification.
+
+== Install Camel JBang
+
+include::../../install.adoc[see installation]
+
+== How to run
+
+Then you can run the Camel integration using:
+
+[source,shell]
+----
+camel run petstore-api.json application.properties petstore.camel.yaml
+----
+
+And then from another terminal (or run the integration with `--background` 
option),
+then send a message to the REST service.
+
+Just call the petstore REST API to retrieve a pet like this:
+
+[source,shell]
+----
+$ curl -i http://localhost:8080/petstore/pet/1000
+HTTP/1.1 200 OK
+petId: 1000
+transfer-encoding: chunked
+Content-Type: application/json
+
+{
+  "id": 1000,
+  "name": "fluffy",
+  "category": {
+    "id": 1000,
+    "name": "dog"
+  },
+  "photoUrls": [
+    "petstore/v3/photos/1000"
+  ],
+  "tags": [
+    {
+      "id": 1000,
+      "name": "generated"
+    }
+  ],
+  "status": "available"
+}
+
+----
+
+The REST service in Camel is configured to load example response data from a 
directory (`camel.component.rest-openapi.mockIncludePattern = 
file:examples/**,classpath:examples/**`).
+
+== Integration testing
+
+The example provides an automated integration test (`pestore.camel.it.yaml`) 
that you can run with the https://citrusframework.org/[Citrus] test framework.
+Please make sure to install Citrus as a JBang application (see 
link:../../install-citrus.adoc[Citrus installation guide]).
+
+You can run the test with:
+
+[source,shell]
+----
+cd test
+citrus run pestore.camel.it.yaml
+----
+
+The test prepares the complete infrastructure and starts the Camel route 
automatically via JBang.
+The Citrus test loads the Open API specification from the Camel service and 
uses the rules in that specification to verify the response data.
+
+== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+https://camel.apache.org/community/support/[let us know].
+
+We also love contributors, so
+https://camel.apache.org/community/contributing/[get involved] :-)
+
+The Camel riders!
diff --git a/openapi/server/application.properties 
b/openapi/server/application.properties
new file mode 100644
index 0000000..0081528
--- /dev/null
+++ b/openapi/server/application.properties
@@ -0,0 +1,19 @@
+#
+# 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.component.rest-openapi.mockIncludePattern = 
file:examples/**,classpath:examples/**
+camel.server.enabled=true
diff --git a/openapi/server/examples/pet/1000.json 
b/openapi/server/examples/pet/1000.json
new file mode 100644
index 0000000..eee6fad
--- /dev/null
+++ b/openapi/server/examples/pet/1000.json
@@ -0,0 +1,18 @@
+{
+  "id": 1000,
+  "name": "fluffy",
+  "category": {
+    "id": 1000,
+    "name": "dog"
+  },
+  "photoUrls": [
+    "petstore/v3/photos/1000"
+  ],
+  "tags": [
+    {
+      "id": 1000,
+      "name": "generated"
+    }
+  ],
+  "status": "available"
+}
diff --git a/openapi/server/petstore-api.json b/openapi/server/petstore-api.json
new file mode 100644
index 0000000..89f9c02
--- /dev/null
+++ b/openapi/server/petstore-api.json
@@ -0,0 +1,299 @@
+{
+  "openapi": "3.0.2",
+  "info": {
+    "title": "Swagger Petstore",
+    "version": "1.0.1",
+    "description": "This is a sample server Petstore server.",
+    "license": {
+      "name": "Apache 2.0",
+      "url": "http://www.apache.org/licenses/LICENSE-2.0.html";
+    }
+  },
+  "servers": [
+    {
+      "url": "{scheme}://{host}/{basePath}",
+      "variables": {
+        "scheme": {
+          "enum": [
+            "https",
+            "http"
+          ],
+          "default": "http"
+        },
+        "host": {
+          "default": "localhost:8080"
+        },
+        "basePath": {
+          "default": "/petstore"
+        }
+      }
+    }
+  ],
+  "paths": {
+    "/pet": {
+      "put": {
+        "requestBody": {
+          "description": "Pet object that needs to be added to the store",
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/Pet"
+              }
+            },
+            "application/xml": {
+              "schema": {
+                "$ref": "#/components/schemas/Pet"
+              }
+            }
+          },
+          "required": true
+        },
+        "tags": [
+          "pet"
+        ],
+        "responses": {
+          "204": {
+            "description": "No content"
+          },
+          "400": {
+            "description": "Invalid ID supplied"
+          },
+          "404": {
+            "description": "Pet not found"
+          },
+          "405": {
+            "description": "Validation exception"
+          }
+        },
+        "operationId": "updatePet",
+        "summary": "Update an existing pet",
+        "description": ""
+      },
+      "post": {
+        "requestBody": {
+          "description": "Pet object that needs to be added to the store",
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/Pet"
+              }
+            },
+            "application/xml": {
+              "schema": {
+                "$ref": "#/components/schemas/Pet"
+              }
+            }
+          },
+          "required": true
+        },
+        "tags": [
+          "pet"
+        ],
+        "responses": {
+          "201": {
+            "description": "Created"
+          },
+          "405": {
+            "description": "Invalid input"
+          }
+        },
+        "operationId": "addPet",
+        "summary": "Add a new pet to the store",
+        "description": ""
+      }
+    },
+    "/pet/{petId}": {
+      "get": {
+        "tags": [
+          "pet"
+        ],
+        "parameters": [
+          {
+            "name": "petId",
+            "description": "ID of pet to return",
+            "schema": {
+              "format": "int64",
+              "type": "integer"
+            },
+            "in": "path",
+            "required": true
+          },
+          {
+            "name": "verbose",
+            "description": "Output details",
+            "schema": {
+              "type": "boolean"
+            },
+            "in": "query",
+            "required": false
+          }
+        ],
+        "responses": {
+          "200": {
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Pet"
+                }
+              },
+              "application/xml": {
+                "schema": {
+                  "$ref": "#/components/schemas/Pet"
+                }
+              }
+            },
+            "description": "successful operation"
+          },
+          "400": {
+            "description": "Invalid ID supplied"
+          },
+          "404": {
+            "description": "Pet not found"
+          }
+        },
+        "operationId": "getPetById",
+        "summary": "Find pet by ID",
+        "description": "Returns a single pet"
+      },
+      "delete": {
+        "tags": [
+          "pet"
+        ],
+        "parameters": [
+          {
+            "name": "petId",
+            "description": "Pet id to delete",
+            "schema": {
+              "format": "int64",
+              "type": "integer"
+            },
+            "in": "path",
+            "required": true
+          }
+        ],
+        "responses": {
+          "204": {
+            "description": "No content"
+          },
+          "400": {
+            "description": "Invalid ID supplied"
+          },
+          "404": {
+            "description": "Pet not found"
+          }
+        },
+        "operationId": "deletePet",
+        "summary": "Deletes a pet",
+        "description": ""
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "Category": {
+        "type": "object",
+        "properties": {
+          "id": {
+            "format": "int64",
+            "type": "integer"
+          },
+          "name": {
+            "type": "string"
+          }
+        },
+        "xml": {
+          "name": "Category"
+        }
+      },
+      "Tag": {
+        "type": "object",
+        "properties": {
+          "id": {
+            "format": "int64",
+            "type": "integer"
+          },
+          "name": {
+            "type": "string"
+          }
+        },
+        "xml": {
+          "name": "Tag"
+        }
+      },
+      "Pet": {
+        "required": [
+          "category",
+          "name",
+          "status"
+        ],
+        "type": "object",
+        "properties": {
+          "id": {
+            "format": "int64",
+            "type": "integer"
+          },
+          "category": {
+            "$ref": "#/components/schemas/Category"
+          },
+          "name": {
+            "type": "string",
+            "example": "doggie"
+          },
+          "photoUrls": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            },
+            "xml": {
+              "name": "photoUrl",
+              "wrapped": true
+            }
+          },
+          "tags": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/Tag"
+            },
+            "xml": {
+              "name": "tag",
+              "wrapped": true
+            }
+          },
+          "status": {
+            "description": "pet status in the store",
+            "enum": [
+              "available",
+              "pending",
+              "sold"
+            ],
+            "type": "string"
+          }
+        },
+        "xml": {
+          "name": "Pet"
+        }
+      },
+      "ApiResponse": {
+        "type": "object",
+        "properties": {
+          "code": {
+            "format": "int32",
+            "type": "integer"
+          },
+          "type": {
+            "type": "string"
+          },
+          "message": {
+            "type": "string"
+          }
+        }
+      }
+    }
+  },
+  "tags": [
+    {
+      "name": "pet",
+      "description": "Everything about your Pets"
+    }
+  ]
+}
diff --git a/openapi/server/petstore.camel.yaml 
b/openapi/server/petstore.camel.yaml
new file mode 100644
index 0000000..1ae795f
--- /dev/null
+++ b/openapi/server/petstore.camel.yaml
@@ -0,0 +1,6 @@
+- restConfiguration:
+    clientRequestValidation: true
+    apiContextPath: openapi
+- rest:
+    openApi:
+      specification: petstore-api.json
diff --git a/openapi/server/test/examples/pet/1000.json 
b/openapi/server/test/examples/pet/1000.json
new file mode 100644
index 0000000..eee6fad
--- /dev/null
+++ b/openapi/server/test/examples/pet/1000.json
@@ -0,0 +1,18 @@
+{
+  "id": 1000,
+  "name": "fluffy",
+  "category": {
+    "id": 1000,
+    "name": "dog"
+  },
+  "photoUrls": [
+    "petstore/v3/photos/1000"
+  ],
+  "tags": [
+    {
+      "id": 1000,
+      "name": "generated"
+    }
+  ],
+  "status": "available"
+}
diff --git a/openapi/server/test/jbang.properties 
b/openapi/server/test/jbang.properties
new file mode 100644
index 0000000..8ff5693
--- /dev/null
+++ b/openapi/server/test/jbang.properties
@@ -0,0 +1,2 @@
+# Declare required additional dependencies
+run.deps=org.citrusframework:citrus-camel:4.5.0,org.citrusframework:citrus-openapi:4.5.0,io.vertx:vertx-core:4.5.11
diff --git a/openapi/server/test/petstore-api.json 
b/openapi/server/test/petstore-api.json
new file mode 100644
index 0000000..89f9c02
--- /dev/null
+++ b/openapi/server/test/petstore-api.json
@@ -0,0 +1,299 @@
+{
+  "openapi": "3.0.2",
+  "info": {
+    "title": "Swagger Petstore",
+    "version": "1.0.1",
+    "description": "This is a sample server Petstore server.",
+    "license": {
+      "name": "Apache 2.0",
+      "url": "http://www.apache.org/licenses/LICENSE-2.0.html";
+    }
+  },
+  "servers": [
+    {
+      "url": "{scheme}://{host}/{basePath}",
+      "variables": {
+        "scheme": {
+          "enum": [
+            "https",
+            "http"
+          ],
+          "default": "http"
+        },
+        "host": {
+          "default": "localhost:8080"
+        },
+        "basePath": {
+          "default": "/petstore"
+        }
+      }
+    }
+  ],
+  "paths": {
+    "/pet": {
+      "put": {
+        "requestBody": {
+          "description": "Pet object that needs to be added to the store",
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/Pet"
+              }
+            },
+            "application/xml": {
+              "schema": {
+                "$ref": "#/components/schemas/Pet"
+              }
+            }
+          },
+          "required": true
+        },
+        "tags": [
+          "pet"
+        ],
+        "responses": {
+          "204": {
+            "description": "No content"
+          },
+          "400": {
+            "description": "Invalid ID supplied"
+          },
+          "404": {
+            "description": "Pet not found"
+          },
+          "405": {
+            "description": "Validation exception"
+          }
+        },
+        "operationId": "updatePet",
+        "summary": "Update an existing pet",
+        "description": ""
+      },
+      "post": {
+        "requestBody": {
+          "description": "Pet object that needs to be added to the store",
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/Pet"
+              }
+            },
+            "application/xml": {
+              "schema": {
+                "$ref": "#/components/schemas/Pet"
+              }
+            }
+          },
+          "required": true
+        },
+        "tags": [
+          "pet"
+        ],
+        "responses": {
+          "201": {
+            "description": "Created"
+          },
+          "405": {
+            "description": "Invalid input"
+          }
+        },
+        "operationId": "addPet",
+        "summary": "Add a new pet to the store",
+        "description": ""
+      }
+    },
+    "/pet/{petId}": {
+      "get": {
+        "tags": [
+          "pet"
+        ],
+        "parameters": [
+          {
+            "name": "petId",
+            "description": "ID of pet to return",
+            "schema": {
+              "format": "int64",
+              "type": "integer"
+            },
+            "in": "path",
+            "required": true
+          },
+          {
+            "name": "verbose",
+            "description": "Output details",
+            "schema": {
+              "type": "boolean"
+            },
+            "in": "query",
+            "required": false
+          }
+        ],
+        "responses": {
+          "200": {
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Pet"
+                }
+              },
+              "application/xml": {
+                "schema": {
+                  "$ref": "#/components/schemas/Pet"
+                }
+              }
+            },
+            "description": "successful operation"
+          },
+          "400": {
+            "description": "Invalid ID supplied"
+          },
+          "404": {
+            "description": "Pet not found"
+          }
+        },
+        "operationId": "getPetById",
+        "summary": "Find pet by ID",
+        "description": "Returns a single pet"
+      },
+      "delete": {
+        "tags": [
+          "pet"
+        ],
+        "parameters": [
+          {
+            "name": "petId",
+            "description": "Pet id to delete",
+            "schema": {
+              "format": "int64",
+              "type": "integer"
+            },
+            "in": "path",
+            "required": true
+          }
+        ],
+        "responses": {
+          "204": {
+            "description": "No content"
+          },
+          "400": {
+            "description": "Invalid ID supplied"
+          },
+          "404": {
+            "description": "Pet not found"
+          }
+        },
+        "operationId": "deletePet",
+        "summary": "Deletes a pet",
+        "description": ""
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "Category": {
+        "type": "object",
+        "properties": {
+          "id": {
+            "format": "int64",
+            "type": "integer"
+          },
+          "name": {
+            "type": "string"
+          }
+        },
+        "xml": {
+          "name": "Category"
+        }
+      },
+      "Tag": {
+        "type": "object",
+        "properties": {
+          "id": {
+            "format": "int64",
+            "type": "integer"
+          },
+          "name": {
+            "type": "string"
+          }
+        },
+        "xml": {
+          "name": "Tag"
+        }
+      },
+      "Pet": {
+        "required": [
+          "category",
+          "name",
+          "status"
+        ],
+        "type": "object",
+        "properties": {
+          "id": {
+            "format": "int64",
+            "type": "integer"
+          },
+          "category": {
+            "$ref": "#/components/schemas/Category"
+          },
+          "name": {
+            "type": "string",
+            "example": "doggie"
+          },
+          "photoUrls": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            },
+            "xml": {
+              "name": "photoUrl",
+              "wrapped": true
+            }
+          },
+          "tags": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/Tag"
+            },
+            "xml": {
+              "name": "tag",
+              "wrapped": true
+            }
+          },
+          "status": {
+            "description": "pet status in the store",
+            "enum": [
+              "available",
+              "pending",
+              "sold"
+            ],
+            "type": "string"
+          }
+        },
+        "xml": {
+          "name": "Pet"
+        }
+      },
+      "ApiResponse": {
+        "type": "object",
+        "properties": {
+          "code": {
+            "format": "int32",
+            "type": "integer"
+          },
+          "type": {
+            "type": "string"
+          },
+          "message": {
+            "type": "string"
+          }
+        }
+      }
+    }
+  },
+  "tags": [
+    {
+      "name": "pet",
+      "description": "Everything about your Pets"
+    }
+  ]
+}
diff --git a/openapi/server/test/petstore.camel.it.yaml 
b/openapi/server/test/petstore.camel.it.yaml
new file mode 100644
index 0000000..d2d3576
--- /dev/null
+++ b/openapi/server/test/petstore.camel.it.yaml
@@ -0,0 +1,27 @@
+name: petstore-test
+description: Sample test in YAML
+variables:
+  - name: petId
+    value: 1000
+actions:
+  - camel:
+      jbang:
+        run:
+          integration:
+            name: "petstore"
+            file: "../petstore.camel.yaml"
+            systemProperties:
+              file: "../application.properties"
+          resources:
+            - "petstore-api.json"
+  - openapi:
+      specification: "http://localhost:8080/openapi";
+      client: "http://localhost:8080/petstore";
+      sendRequest:
+        operation: getPetById
+  - openapi:
+      specification: "http://localhost:8080/openapi";
+      client: "http://localhost:8080/petstore";
+      receiveResponse:
+        operation: getPetById
+        status: 200

Reply via email to