diff --git a/content/docs/_index.md b/content/docs/_index.md index f812f134..5e68ffe0 100644 --- a/content/docs/_index.md +++ b/content/docs/_index.md @@ -34,10 +34,10 @@ This documentation is organized into several sections that you can access from t - **[Quickstart](quickstart/)** - Learn the basics with a quick tutorial - **[Designer](designer/)** - Explore the visual designer interface and features - **[DataMapper](datamapper/)** - Transform and map data between different formats +- **[REST](rest/)** - Work with REST APIs in your integrations diff --git a/content/docs/rest/01_api_first/_index.md b/content/docs/rest/01_api_first/_index.md new file mode 100644 index 00000000..23c84340 --- /dev/null +++ b/content/docs/rest/01_api_first/_index.md @@ -0,0 +1,252 @@ +--- +title: "API-First Approach" +description: "Link OpenAPI specifications to REST endpoints in Kaoto" +date: 2026-03-31 +weight: 1 +--- + +## Introduction + +The API-first approach in Kaoto allows you to link an OpenAPI specification directly to your REST service. Instead of manually creating each endpoint, you reference the OpenAPI file and Apache Camel reads the specification at runtime to create all REST endpoints. The OpenAPI specification file must be kept with your integration as Camel needs it to run. Kaoto visualizes the direct route in the Design view. + +> [!NOTE] +> **OpenAPI vs OpenAI**: OpenAPI (formerly known as Swagger) is an API specification standard and is not related to OpenAI (the company behind ChatGPT). The Apache Camel OpenAPI component works with OpenAPI specifications for REST API integration. + +## Create the Route File in Kaoto +### Step 1: Link the OpenAPI Specification + +This is the key step in the API-first approach. + +1. Click **Rest** in the top navigation, then **Actions**, and select **+ Add Service** from the dropdown + +2. Add the `book-summary-api.openapi.yaml` file to your workspace at the same level as your route file + +3. Click the pencil icon next to **Open Api** and enter the path to your OpenAPI file + +This adds the REST DSL block with the `openApi.specification` property: + +```yaml +- rest: + id: rest-1736 + openApi: + specification: book-summary-api.openapi.yaml +``` + +**This is the API-first magic**: By linking the OpenAPI specification, Apache Camel: +1. Reads the OpenAPI file at runtime (the file must be present when running) +2. Creates all REST endpoints defined in the specification +3. Maps operations to direct routes using `operationId` +4. Builds the complete REST API structure from the specification + +> [!IMPORTANT] +> The `specification` path is relative to your workspace folder. The OpenAPI specification file (`book-summary-api.openapi.yaml`) must be kept with your integration - Camel needs it at runtime to create the REST endpoints. Make sure it's in the same directory as your route file. Kaoto will validate the file path. + +### Step 2: Implement the Direct Route + +The OpenAPI specification uses the `operationId` property to map the operation to `direct:getBookFunExtract`. Now you'll implement this direct route in Kaoto using the Design view to add steps visually. + +1. **Replace the timer component**: Click on the timer component and replace it with a **Direct** component + +2. **Configure the direct endpoint**: In **Endpoint Properties** > **name**, enter `getBookFunExtract` + +3. **Add removeHeaders processor**: Insert a **removeHeaders** processor between the direct endpoint and the setBody processor + - Set the **pattern** to `CamelHttp*` + - This removes all headers starting with `CamelHttp` that might interfere with the external API call + +4. **Add first setHeader processor**: After removeHeaders, add a **setHeader** processor + - Set **name** to `x-rapidapi-host` + - Change the expression type from **Simple** to **Constant** + - Set **expression** to `project-gutenberg-free-books-api1.p.rapidapi.com` + - This sets the RapidAPI host header required by the Gutenberg API + +5. **Add second setHeader processor**: Add another **setHeader** processor + - Set **name** to `x-rapidapi-key` + - Keep expression type as **Simple** + - Set **expression** to `{{gutenberg.api.key}}` + - Add your API key in the `application.properties` file in your workspace + - This sets your API key using a property placeholder for security + +6. **Add toD processor**: Add a **toD** (dynamic to) processor + - Set the **uri** to: `https://project-gutenberg-free-books-api1.p.rapidapi.com/books/${header.id}?bridgeEndpoint=true` + - This makes a dynamic HTTP call to the Gutenberg API using the book ID from the path parameter + +7. **Update setBody processor**: Modify the **setBody** processor + - Change expression type to **JSONPath** + - Set **expression** to `$.results[0].summary` + - This extracts the book summary from the JSON response + +8. **Update log processor**: Modify the **log** processor + - Set **message** to `Book summary: ${body}` + - This logs the book summary for debugging and verification + +{{< img-toggle src="./complete-route.png" lang="yaml" >}} +- route: + from: + uri: direct + parameters: + name: getBookFunExtract + steps: + - removeHeaders: + id: removeHeaders-4268 + pattern: CamelHttp* + - setHeader: + id: setHeader-3265 + name: x-rapidapi-host + constant: + expression: project-gutenberg-free-books-api1.p.rapidapi.com + - setHeader: + id: setHeader-2139 + simple: + expression: "{{gutenberg.api.key}}" + name: x-rapidapi-key + - toD: + id: toD-4177 + uri: https://project-gutenberg-free-books-api1.p.rapidapi.com/books/${header.id}?bridgeEndpoint=true + parameters: {} + - setBody: + id: setBody-2130 + jsonpath: + expression: $.results[0].summary + - log: + message: '"Book summary: ${body}"' + id: from-6080 + id: route-1416 +{{< /img-toggle >}} + +## Testing in Kaoto + +### Run the Integration + +Before running your integration, you need to configure Kaoto's run settings. Follow these steps carefully: + +#### Step 1: Open VS Code Settings + +1. Open VS Code Settings: + - **macOS**: Press `Cmd + ,` or go to **Code** > **Preferences** > **Settings** + - **Windows/Linux**: Press `Ctrl + ,` or go to **File** > **Preferences** > **Settings** + +2. **Important**: Click on the **Workspace** tab at the top of the settings window (not "User") + - This ensures settings only apply to this project + - Creates a `.vscode/settings.json` file in your project folder + +#### Step 2: Configure Kaoto Run Settings + +1. In the search bar, type `kaoto` to filter Kaoto-related settings + +2. Find and configure **Kaoto: Run Arguments** and **Kaoto: Run Folder**: + - Add: `--management-port=8080` + - This sets a separate port for JBang management to avoid conflicts + +{{< figure src="settings1.png" alt="Kaoto settings run arguments" caption="Kaoto settings run arguments" class="image" >}} + +{{< figure src="settings2.png" alt="Kaoto settings run folder" caption="Kaoto settings run folder" class="image" >}} + +> [!IMPORTANT] +> **Why Workspace-Level Settings Matter** +> +> Always configure Kaoto run settings at the **workspace level** (not globally): +> +> - **Global settings problem**: Apply to all VS Code projects, meaning you can only run one integration at a time across all your projects +> - **Workspace settings solution**: Each project has its own isolated configuration in `.vscode/settings.json` +> - **Benefit**: Run multiple integrations simultaneously in different workspaces without conflicts +> - **How to verify**: Check that you clicked the "Workspace" tab in settings, not "User" + +#### Step 3: Reload and Run + +1. **Reload VS Code**: Press `Cmd/Ctrl + Shift + P`, type "Reload Window", and press Enter + - This ensures VS Code picks up the new settings + +2. **Run the integration**: In Kaoto, click the **Run** button in the folder + - Kaoto will start your integration using JBang + - You should see output in the terminal showing the integration starting up + +{{< figure src="run-button.png" alt="Running the route" caption="Running the route" class="image" >}} + +### Test the Endpoint + +Open a terminal and run: + +```bash +curl http://localhost:8080/books/1342/fun-extract +``` + +You should receive a JSON response with the book summary for "Pride and Prejudice" (book ID 1342). + +### Try Different Books + +Test with other Project Gutenberg book IDs: + +```bash + +# Frankenstein +curl http://localhost:8080/books/84/fun-extract + +# The Adventures of Sherlock Holmes +curl http://localhost:8080/books/1661/fun-extract +``` + +## Key Concepts + +### API-First: Link, Don't Create + +The API-first approach means: +- **Link** the OpenAPI specification in your REST service +- **Don't manually create** each endpoint in Kaoto +- Camel **reads the spec at runtime** to create all endpoints +- The **OpenAPI file must be kept** with your integration +- Kaoto **visualizes** the operation implementation + +[Learn more about Apache Camel REST DSL](https://camel.apache.org/manual/rest-dsl.html) + +### openApi.specification Property + +The `openApi.specification` property is the core of API-first: +```yaml +- rest: + openApi: + specification: book-summary-api.openapi.yaml +``` + +This single property tells Camel to: +- Load and parse the OpenAPI specification file at runtime +- Create REST endpoints for all paths defined in the spec +- Use `operationId` to map operations to direct routes +- Build the complete REST API structure from the specification + +The OpenAPI specification file must be present when running the integration - it's not just used during development. + +[Learn more about OpenAPI and Camel](https://camel.apache.org/components/latest/others/openapi-java.html) + +### Direct Routes as Implementation Targets + +Direct routes act as internal endpoints that can be called from REST operations. This separation provides: +- **Reusability**: The same direct route can be called from multiple REST operations +- **Testability**: Direct routes can be tested independently +- **Maintainability**: Implementation logic is separate from API definition + +[Learn more about Camel Direct Component](https://camel.apache.org/components/latest/direct-component.html) + +### Property Placeholders + +Using property placeholders like `{{gutenberg.api.key}}` allows you to: +- Keep sensitive data out of your code +- Use different values in different environments +- Manage configuration centrally in `application.properties` + +[Learn more about Property Placeholders](https://camel.apache.org/manual/using-propertyplaceholder.html) + +## Summary + +This documentation demonstrated: + +1. ✅ Using the API-first approach by linking an OpenAPI specification +2. ✅ Letting Camel read the spec at runtime to create REST endpoints +3. ✅ Understanding that the OpenAPI file must be kept with your integration +4. ✅ Visualizing the linked endpoints in Kaoto's Design view +5. ✅ Implementing only the direct route logic (not the endpoints themselves) +6. ✅ Running and testing the REST API using Kaoto + +## Next Steps + +- **[Code-First Approach](../02_code_first/)** - Learn how to import OpenAPI specs using the visual REST Import Wizard +- **[Extending with REST Editor](../03_rest_editor/)** - Add new endpoints using the visual REST Editor \ No newline at end of file diff --git a/content/docs/rest/01_api_first/complete-route.png b/content/docs/rest/01_api_first/complete-route.png new file mode 100644 index 00000000..9d33f376 Binary files /dev/null and b/content/docs/rest/01_api_first/complete-route.png differ diff --git a/content/docs/rest/01_api_first/rest-actions.png b/content/docs/rest/01_api_first/rest-actions.png new file mode 100644 index 00000000..09b4618f Binary files /dev/null and b/content/docs/rest/01_api_first/rest-actions.png differ diff --git a/content/docs/rest/01_api_first/run-button.png b/content/docs/rest/01_api_first/run-button.png new file mode 100644 index 00000000..6e536385 Binary files /dev/null and b/content/docs/rest/01_api_first/run-button.png differ diff --git a/content/docs/rest/01_api_first/settings1.png b/content/docs/rest/01_api_first/settings1.png new file mode 100644 index 00000000..e2e595f7 Binary files /dev/null and b/content/docs/rest/01_api_first/settings1.png differ diff --git a/content/docs/rest/01_api_first/settings2.png b/content/docs/rest/01_api_first/settings2.png new file mode 100644 index 00000000..871a1862 Binary files /dev/null and b/content/docs/rest/01_api_first/settings2.png differ diff --git a/content/docs/rest/02_code_first/_index.md b/content/docs/rest/02_code_first/_index.md new file mode 100644 index 00000000..012b4cc4 --- /dev/null +++ b/content/docs/rest/02_code_first/_index.md @@ -0,0 +1,330 @@ +--- +title: "Code-First Approach" +description: "Use Kaoto's REST Import Wizard to generate endpoints and build routes visually" +date: 2026-03-31 +weight: 2 +--- + +## Introduction + +The code-first approach uses Kaoto's REST Import Wizard to import OpenAPI specifications and automatically generate REST endpoints with route stubs. Unlike the API-first approach (which links the spec at runtime), the wizard creates explicit endpoint definitions in your route file. Once generated, the OpenAPI file is no longer needed - all endpoints are defined in your route file. You then implement the route logic visually using Kaoto's component catalog and Design view. + +## Import OpenAPI Specification with Kaoto + +### Step 1: Configure in the REST Import Wizard + +1. In the Kaoto extension, click in Import next to OpenAPI and it will open the REST Import Wizard. + +{{< figure src="rest-import-button.png" alt="REST Import button in Kaoto" caption="Kaoto's REST Import Wizard button" class="image" >}} + +2. In the Kaoto Import Wizard, select **Upload file** as the source +3. Click **Choose file** and select the `book-summary-api.openapi.yaml` file + +4. The wizard will parse the file and show all discovered operations + +{{< figure src="rest-import-wizard-1.png" alt="REST Import Wizard - Step 1 in Kaoto" caption="Kaoto parses the OpenAPI file and shows operations" class="image" >}} + +You should see the `GET /books/{id}/fun-extract` operation listed. + +5. Configure the following options (both should be checked): + +- ☑ **Create REST DSL operations** - Generates REST endpoint definitions +- ☑ **Create routes with direct endpoints** - Generates route stubs for each operation + +{{< figure src="rest-import-generation.png" alt="REST Import generation options" caption="Configure REST DSL and route generation options" class="image" >}} + +6. Choose the folder to save the information and then give a name to the route. + +{{< figure src="rest-import-wizard-2.png" alt="REST Import Wizard - Step 2 in Kaoto" caption="Configure how Kaoto generates the routes" class="image" >}} + + +### Step 2: Review Generated Structure in Kaoto + +After importing, Kaoto generates and displays in the Design view: + +1. **REST DSL definition** - Complete endpoint with parameters and responses +2. **Direct route stub** - A placeholder route ready for implementation + +The generated structure looks like this: + +{{< img-toggle src="imported-route.png" lang="yaml" >}} +- rest: + id: rest-1774958475751 + get: + - id: getBookFunExtract + path: /books/{id}/fun-extract + routeId: route-getBookFunExtract + to: direct:getBookFunExtract + description: Fetches a book from Project Gutenberg and generates an AI extract using OpenAI + produces: application/json + param: + - name: id + type: path + required: true + description: Project Gutenberg book ID (e.g., 11 for Alice's Adventures in Wonderland) + dataType: integer + responseMessage: + - code: "200" + message: Book fun extract generated successfully + contentType: application/json + - code: "404" + message: Book not found in Project Gutenberg + - code: "500" + message: Server error during processing +- route: + id: route-getBookFunExtract + from: + uri: direct:getBookFunExtract + id: direct-from-getBookFunExtract + steps: + - setBody: + constant: Operation getBookFunExtract not yet implemented +{{< /img-toggle >}} + +Your route file now contains the REST endpoint definition, and the direct route stub. + +## Implement the Route Visually in Kaoto + +Now you'll implement the logic by reusing the route from the API-first approach and adding OpenAI integration. + +> [!NOTE] +> This section assumes you've completed the [API-First Approach](../01_api_first/) documentation example. If not, complete that first or refer to it for the Gutenberg API integration steps. + +### Step 3: Copy Route from API-First Implementation + +1. Open the route file from the API-first documentation example (e.g., `book-api.camel.yaml`) +2. In Kaoto's Design view, locate the `route-getBookFunExtract` route +3. Right-click on the **route** (not on individual steps) and select **Copy** + +{{< figure src="copy-route.png" alt="Copy route in Kaoto" caption="Copy the complete route from API-first implementation" class="image" >}} + +### Step 4: Paste Route into Code-First Route + +1. Switch back to your code-first route file +2. In the Design view, find the `route-getBookFunExtract` route +3. Right-click on the Design canvas itself (not on the setBody step) and select **Paste**. This pastes the complete route from the API-first route. + +{{< figure src="paste-route.png" alt="Paste route in Kaoto" caption="Paste the complete route into the code-first route file" class="image" >}} + +### Step 5: Drag and Drop Steps to Reorder + +1. In the Design view, locate the `removeHeaders` step +2. Click and drag the `removeHeaders` step +3. Drop it directly after the `direct` component (at the beginning of the route) +4. Do the same with the other components. + +The new route structure after drag and drop: + +{{< img-toggle src="after-drag-and-drop.png" lang="yaml" >}} +- route: + id: route-getBookFunExtract + from: + uri: direct:getBookFunExtract + id: direct-from-getBookFunExtract + steps: + - removeHeaders: + id: removeHeaders-4268-1881 + pattern: CamelHttp* + - setHeader: + id: setHeader-3265-3267 + name: x-rapidapi-host + constant: + expression: project-gutenberg-free-books-api1.p.rapidapi.com + - setHeader: + id: setHeader-2139-3021 + simple: + expression: "{{gutenberg.api.key}}" + name: x-rapidapi-key + - toD: + id: toD-4177-4046 + uri: https://project-gutenberg-free-books-api1.p.rapidapi.com/books/${header.id}?bridgeEndpoint=true + parameters: {} + - setBody: + id: setBody-2130-2169 + jsonpath: + expression: $.results[0].summary + - log: + message: '"Book summary: ${body}"' + - setBody: + constant: Operation getBookFunExtract not yet implemented +{{< /img-toggle >}} + +### Step 6: Delete Placeholder and Extra Steps + +1. Delete the placeholder `setBody` step at the end (the one with "Operation getBookFunExtract not yet implemented") +2. Delete any remaining copied `direct` component + +Your route now has the complete Gutenberg API integration in the correct order. + +### Step 7: Add OpenAI Integration from Catalog + +Now add the AI-powered fun extract generation: + +1. Hover over the arrow after the `setBody` step (the one that extracts `$.results[0].summary`) +2. Click the **+** button that appears +3. In the catalog search, type `openai` +4. Select **OpenAI** component +5. Configure in Kaoto's form: + +| Property | Value | +|----------|-------| +| **Operation** | chat-completion | +| **Api Key** | OLLAMA-LOCAL-KEY | +| **Base Url** | http://localhost:11434/v1 | +| **Model** | granite4:tiny-h | +| **System Message** | Summarize this text into a couple of short sentences and give it a funny twist | + +This sends the book summary to your local Ollama instance running the Granite 4 model for AI-powered fun extracts. + +> [!TIP] +> For more details on configuring OpenAI in Kaoto, refer to the [Quickstart guide](../../quickstart/). + +The OpenAI component is now inserted between `setBody` and `log`, completing your route. + +## Complete Route + +Your final route should look like this: +{{< img-toggle src="./complete-route.png" lang="yaml" >}} +- rest: + id: rest-1775038763756 + get: + - id: getBookFunExtract + path: /books/{id}/fun-extract + routeId: route-getBookFunExtract + to: direct:getBookFunExtract + description: Fetches a book from Project Gutenberg and generates an AI extract + using OpenAI + produces: application/json + param: + - name: id + type: path + required: true + description: Project Gutenberg book ID (e.g., 11 for Alice's Adventures in + Wonderland) + dataType: integer + responseMessage: + - code: "200" + message: Book fun extract generated successfully + contentType: application/json + - code: "404" + message: Book not found in Project Gutenberg + - code: "500" + message: Server error during processing +- route: + id: route-getBookFunExtract + from: + uri: direct:getBookFunExtract + id: direct-from-getBookFunExtract + steps: + - removeHeaders: + id: removeHeaders-4268-1881 + pattern: CamelHttp* + - setHeader: + id: setHeader-3265-3267 + name: x-rapidapi-host + constant: + expression: project-gutenberg-free-books-api1.p.rapidapi.com + - setHeader: + id: setHeader-2139-3021 + simple: + expression: "{{gutenberg.api.key}}" + name: x-rapidapi-key + - toD: + id: toD-4177-4046 + uri: https://project-gutenberg-free-books-api1.p.rapidapi.com/books/${header.id}?bridgeEndpoint=true + parameters: {} + - setBody: + id: setBody-2130-2169 + jsonpath: + expression: $.results[0].summary + - to: + id: to-3162 + uri: openai + parameters: + operation: chat-completion + apiKey: OLLAMA-LOCAL-KEY + baseUrl: http://localhost:11434/v1 + model: granite4:tiny-h + systemMessage: Summarize this text into a couple of short sentences and give it + a funny twist + - log: + message: '"Book summary: ${body}"' +{{< /img-toggle >}} + +## Testing in Kaoto + +### Run the Integration + +1. Make sure Ollama is running with the Granite 4 model +2. In Kaoto's toolbar, click the **Run** button. Make sure your application.properties and the new route are in the same folder. +3. Kaoto will start your integration using JBang +4. Watch the Design view to see your routes activate + +### Test the Endpoint + +Open a terminal and run: + +```bash +curl http://localhost:8080/books/1342/fun-extract +``` + +You should receive an AI-generated fun extract of "Pride and Prejudice" (book ID 1342). + +### Try Different Books + +```bash +# Frankenstein +curl http://localhost:8080/books/84/fun-extract + +# The Adventures of Sherlock Holmes +curl http://localhost:8080/books/1661/fun-extract +``` + +Each request will return a unique AI-generated fun extract! + +## Key Concepts + +### Apache Camel REST DSL + +The REST DSL in Apache Camel provides a declarative way to define REST APIs. It allows you to specify REST endpoints, their operations, parameters, and responses in a structured format. + +[Learn more about Apache Camel REST DSL](https://camel.apache.org/manual/rest-dsl.html) + +### Kaoto REST Import Wizard + +Kaoto's REST Import Wizard automates: +1. Parsing OpenAPI specifications +2. Generating explicit REST DSL endpoint definitions (not just linking) +3. Creating direct route stubs ready for implementation + +Unlike API-first (which links the spec at runtime), the wizard creates the actual endpoint definitions in your route file. Once generated, the OpenAPI file is no longer needed. + +[Learn more about OpenAPI and Camel](https://camel.apache.org/components/latest/others/openapi-java.html) + +### Direct Component + +The Direct component provides synchronous, in-memory communication between routes, allowing you to separate REST endpoint definitions from their implementation logic. + +[Learn more about Camel Direct Component](https://camel.apache.org/components/latest/direct-component.html) + +### Combining Multiple APIs + +This documentation example demonstrates combining two external APIs: +1. **Project Gutenberg API** (via RapidAPI) - Fetches book data +2. **OpenAI API** (via Ollama) - Generates AI summaries + +Camel makes it easy to orchestrate multiple services in a single route. + +## Summary + +This documentation demonstrated: + +1. ✅ Using Kaoto's REST Import Wizard to generate REST endpoints from OpenAPI (no runtime dependency on OpenAPI file) +2. ✅ Building a route visually using Kaoto's Design and component catalog +3. ✅ Configuring components using Kaoto's forms +4. ✅ Connecting to external APIs (Gutenberg and OpenAI) visually +5. ✅ Running and testing the integration using Kaoto's tools + +## Next Steps + +- **[Extending with REST Editor](../03_rest_editor/)** - Learn how to add new endpoints from scratch using the REST Editor diff --git a/content/docs/rest/02_code_first/after-drag-and-drop.png b/content/docs/rest/02_code_first/after-drag-and-drop.png new file mode 100644 index 00000000..a068d9ca Binary files /dev/null and b/content/docs/rest/02_code_first/after-drag-and-drop.png differ diff --git a/content/docs/rest/02_code_first/complete-route.png b/content/docs/rest/02_code_first/complete-route.png new file mode 100644 index 00000000..6cb5d468 Binary files /dev/null and b/content/docs/rest/02_code_first/complete-route.png differ diff --git a/content/docs/rest/02_code_first/copy-route.png b/content/docs/rest/02_code_first/copy-route.png new file mode 100644 index 00000000..a0843b0e Binary files /dev/null and b/content/docs/rest/02_code_first/copy-route.png differ diff --git a/content/docs/rest/02_code_first/imported-route.png b/content/docs/rest/02_code_first/imported-route.png new file mode 100644 index 00000000..628673f7 Binary files /dev/null and b/content/docs/rest/02_code_first/imported-route.png differ diff --git a/content/docs/rest/02_code_first/paste-route.png b/content/docs/rest/02_code_first/paste-route.png new file mode 100644 index 00000000..47e58c65 Binary files /dev/null and b/content/docs/rest/02_code_first/paste-route.png differ diff --git a/content/docs/rest/02_code_first/rest-import-button.png b/content/docs/rest/02_code_first/rest-import-button.png new file mode 100644 index 00000000..1c16e235 Binary files /dev/null and b/content/docs/rest/02_code_first/rest-import-button.png differ diff --git a/content/docs/rest/02_code_first/rest-import-generation.png b/content/docs/rest/02_code_first/rest-import-generation.png new file mode 100644 index 00000000..3fb1ad65 Binary files /dev/null and b/content/docs/rest/02_code_first/rest-import-generation.png differ diff --git a/content/docs/rest/02_code_first/rest-import-wizard-1.png b/content/docs/rest/02_code_first/rest-import-wizard-1.png new file mode 100644 index 00000000..bac7faf5 Binary files /dev/null and b/content/docs/rest/02_code_first/rest-import-wizard-1.png differ diff --git a/content/docs/rest/02_code_first/rest-import-wizard-2.png b/content/docs/rest/02_code_first/rest-import-wizard-2.png new file mode 100644 index 00000000..fb5fc668 Binary files /dev/null and b/content/docs/rest/02_code_first/rest-import-wizard-2.png differ diff --git a/content/docs/rest/03_rest_editor/_index.md b/content/docs/rest/03_rest_editor/_index.md new file mode 100644 index 00000000..c96ef314 --- /dev/null +++ b/content/docs/rest/03_rest_editor/_index.md @@ -0,0 +1,498 @@ +--- +title: "Extending with REST Editor" +description: "Use Kaoto's REST Editor to visually add and manage REST endpoints from scratch" +date: 2026-03-31 +weight: 3 +--- + +## Introduction + +Kaoto's REST Editor provides a visual tree-based interface for creating and managing REST endpoints from scratch in your Camel integrations. Unlike the code-first approach (which generates endpoints from OpenAPI) or API-first (which links a spec at runtime), the REST Editor lets you manually create, configure, and manage individual endpoints through a visual interface without any OpenAPI specification. This approach is ideal for building REST APIs from scratch, extending existing REST APIs, and maintaining your API structure over time. + +## Starting Point + +This example extends the REST API from the [Code-First Approach](../02_code_first/). You can either: +- Continue from your existing route file, or +- Copy the final route from that documentation + +## Open Kaoto's REST Editor + +### Step 1: Open Your Route File in Kaoto + +1. In VS Code, open the route file from Part 2 (e.g., `rest-api.camel.yaml`) +2. Kaoto will automatically open, showing the Canvas view + +### Step 2: Access the REST Editor + +1. In the Kaoto toolbar, click the **REST DSL** button +2. Kaoto's REST Editor will open, displaying your REST structure in a tree view + +{{< figure src="add-rest-configuration.png" alt="Kaoto REST Editor interface" caption="Kaoto's REST Editor shows your API structure in a tree" class="image" >}} + +You should see in the tree: +- Your REST service +- The existing `GET /books/{id}/fun-extract` endpoint +- The associated direct route + +## Add a New Endpoint Using Kaoto's REST Editor + +Now you'll use Kaoto's REST Editor to add a new endpoint for searching popular books. + +### Step 1: Add the GET Operation + +Since the new endpoint shares the same base path (`/books`), we'll add it to the existing REST block. + +> [!TIP] +> **When to Create a New REST Block** +> +> Create a new REST block (using **Actions** > **Add REST** at the top level) when you need: +> - A different base path (e.g., `/authors` instead of `/books`) +> - To organize endpoints by domain or feature area +> +> For this example, both endpoints use `/books/*` paths, so we add the operation to the existing REST block. + +1. In the REST block in the tree, click **Actions** +2. Select **Add Operation** +3. In Kaoto's modal dialog, configure: + +| Property | Value | +|----------|-------| +| **HTTP Method** | GET | +| **Path** | /books/popular | +| **Operation ID** | listBooks | + +Click **Add** to create the operation in the tree. + +{{< figure src="add-operation-modal.png" alt="Add Operation modal dialog" caption="Configure the new GET operation in Kaoto's modal" class="image" >}} + +### Step 2: Configure the Operation in Kaoto's Form + +With the new operation selected in the tree, configure its properties using Kaoto's form: + +| Property | Value | +|----------|-------| +| **Produces** | application/json | +| **Description** | Lists popular books from Project Gutenberg | + +{{< figure src="rest-form.png" alt="REST operation configuration form" caption="Configure operation properties in Kaoto's form" class="image" >}} + +### Step 3: Add Response Messages Using the Form + +Scroll down in Kaoto's configuration form and add response messages: + +1. Click **+** next to **Response Message** +2. Configure the first response in the form: + - **Code**: 200 + - **Message**: Books retrieved successfully + - **Content Type**: application/json + +3. Add a new response again +4. Configure the error response: + - **Code**: 500 + - **Message**: Server error during processing + +Current state of the route file: + +```yaml +- rest: + id: rest-1775038763756 + get: + - id: getBookFunExtract + path: /books/{id}/fun-extract + routeId: route-getBookFunExtract + to: direct:getBookFunExtract + description: Fetches a book from Project Gutenberg and generates an AI extract + using OpenAI + produces: application/json + param: + - name: id + type: path + required: true + description: Project Gutenberg book ID (e.g., 11 for Alice's Adventures in + Wonderland) + dataType: integer + responseMessage: + - code: "200" + message: Book fun extract generated successfully + contentType: application/json + - code: "404" + message: Book not found in Project Gutenberg + - code: "500" + message: Server error during processing + - id: listBooks + path: /books/popular + to: + uri: direct + parameters: + name: direct-listBooks + produces: application/json + description: Lists popular books from Project Gutenberg + responseMessage: + - message: Server error during processing + code: "500" + - message: Books retrieved successfully + code: "200" + contentType: application/json +- route: + id: route-getBookFunExtract + from: + uri: direct:getBookFunExtract + id: direct-from-getBookFunExtract + steps: + - removeHeaders: + id: removeHeaders-4268-1881 + pattern: CamelHttp* + - setHeader: + id: setHeader-3265-3267 + name: x-rapidapi-host + constant: + expression: project-gutenberg-free-books-api1.p.rapidapi.com + - setHeader: + id: setHeader-2139-3021 + simple: + expression: "{{gutenberg.api.key}}" + name: x-rapidapi-key + - toD: + id: toD-4177-4046 + uri: https://project-gutenberg-free-books-api1.p.rapidapi.com/books/${header.id}?bridgeEndpoint=true + parameters: {} + - setBody: + id: setBody-2130-2169 + jsonpath: + expression: $.results[0].summary + - to: + id: to-3162 + uri: openai + parameters: + operation: chat-completion + apiKey: OLLAMA-LOCAL-KEY + baseUrl: http://localhost:11434/v1 + model: granite4:tiny-h + systemMessage: Summarize this text into a couple of short sentences and give it + a funny twist + - log: + message: '"Book summary: ${body}"' +``` + +### Step 4: Create the Direct Route + +1. Next to **Endpoint Name** in Kaoto's form, you'll see a **Create Route** button +2. Click **Create Route** +3. Kaoto will generate a new direct route stub for `direct:listBooks` and show it in the Canvas + +{{< figure src="new-route-created.png" alt="New route created in Canvas" caption="Kaoto generates a direct route stub ready for implementation" class="image" >}} + +## Implement the Popular Books Route in Kaoto + +Now you'll implement the logic using Kaoto's Canvas view. + +### Step 1: Navigate to the New Route in Canvas + +1. In Kaoto's Canvas view, find the `route-listBooks` route +2. You'll see it starts with a `direct` component + +### Step 2: Reuse Steps from the Existing Route + +Since both routes call the same RapidAPI service, you can duplicate the common steps from the existing route: + +1. Navigate to the `route-getBookFunExtract` route in Canvas +2. Select the `removeHeaders` step +3. Right-click over the component and select **Duplicate** + +{{< figure src="duplicate-component.png" alt="Duplicate component context menu" caption="Right-click on a component to duplicate it" class="image" >}} + +4. Drag the duplicated step to the `route-listBooks` route and drop it after the `direct` component +5. Repeat for both `setHeader` steps (x-rapidapi-host and x-rapidapi-key) + +This approach saves time by reusing the exact configuration from the working route. + +### Step 3: Add HTTP Call from Catalog + +1. Click **Add step** in the Canvas +2. Search for `to` in the catalog (not `toD` - we don't need dynamic URI here) +3. Select **To** +4. Configure: **URI** = `https://project-gutenberg-free-books-api1.p.rapidapi.com/books?bridgeEndpoint=true` + +This calls the Gutenberg API to get a list of popular books. + +### Step 4: Extract Book Information + +1. Click **Add step** in the Canvas +2. Search for `setBody` in the catalog +3. Select **Set Body** +4. Configure: + - **Expression Type**: JSONPath + - **Expression**: `$.results[*].['title', 'authors']` + +This extracts just the title and authors from each book in the response. + +### Step 5: Format as Pretty JSON + +1. Click **Add step** in the Canvas +2. Search for `marshal` in the catalog +3. Select **Marshal** +4. Select **JSON** as the data format +5. Enable **Pretty Print**: `true` + +This formats the response as readable JSON. + +### Step 6: Add Logging + +1. Click **Add step** in the Canvas +2. Search for `log` in the catalog +3. Select **Logger** +4. Configure: **Message** = `Books list: ${body}` + +## Complete Route + +Your final route file should now have one REST block with two operations and two routes: + +{{< img-toggle src="./final-route.png" lang="yaml" >}} +- rest: + id: rest-1775038763756 + get: + - id: getBookFunExtract + path: /books/{id}/fun-extract + routeId: route-getBookFunExtract + to: direct:getBookFunExtract + description: Fetches a book from Project Gutenberg and generates an AI extract + using OpenAI + produces: application/json + param: + - name: id + type: path + required: true + description: Project Gutenberg book ID (e.g., 11 for Alice's Adventures in + Wonderland) + dataType: integer + responseMessage: + - code: "200" + message: Book fun extract generated successfully + contentType: application/json + - code: "404" + message: Book not found in Project Gutenberg + - code: "500" + message: Server error during processing + - id: listBooks + path: /books/popular + to: + uri: direct + parameters: + name: direct-listBooks + produces: application/json + description: Lists popular books from Project Gutenberg + responseMessage: + - message: Server error during processing + code: "500" + - message: Books retrieved successfully + code: "200" + contentType: application/json +- route: + id: route-getBookFunExtract + from: + uri: direct:getBookFunExtract + id: direct-from-getBookFunExtract + steps: + - removeHeaders: + id: removeHeaders-4268-1881 + pattern: CamelHttp* + - setHeader: + id: setHeader-3265-3267 + name: x-rapidapi-host + constant: + expression: project-gutenberg-free-books-api1.p.rapidapi.com + - setHeader: + id: setHeader-2139-3021 + simple: + expression: "{{gutenberg.api.key}}" + name: x-rapidapi-key + - toD: + id: toD-4177-4046 + uri: https://project-gutenberg-free-books-api1.p.rapidapi.com/books/${header.id}?bridgeEndpoint=true + parameters: {} + - setBody: + id: setBody-2130-2169 + jsonpath: + expression: $.results[0].summary + - to: + id: to-3162 + uri: openai + parameters: + operation: chat-completion + apiKey: OLLAMA-LOCAL-KEY + baseUrl: http://localhost:11434/v1 + model: granite4:tiny-h + systemMessage: Summarize this text into a couple of short sentences and give it + a funny twist + - log: + message: '"Book summary: ${body}"' +- route: + from: + uri: direct + parameters: + name: direct-listBooks + steps: + - removeHeaders: + id: removeHeaders-4268-1881-1194 + pattern: CamelHttp* + - setHeader: + id: setHeader-3265-3267-3151 + name: x-rapidapi-host + constant: + expression: project-gutenberg-free-books-api1.p.rapidapi.com + - setHeader: + id: setHeader-2139-3021-2084 + simple: + expression: "{{gutenberg.api.key}}" + name: x-rapidapi-key + - to: + id: to-3444 + uri: https://project-gutenberg-free-books-api1.p.rapidapi.com/books?bridgeEndpoint=true + parameters: {} + - setBody: + id: setBody-9923 + jsonpath: + expression: $.results[*].['title', 'authors'] + - marshal: + id: marshal-7672 + json: + prettyPrint: true + - log: + id: log-2120 + message: "Books list: ${body}" + id: route-3988 +{{< /img-toggle >}} + +## Testing the New Endpoint + +### Run the Integration + +1. Ensure your `application.properties` file has your RapidAPI key +2. In Kaoto, click the **Run: folder** button in the folder +3. Kaoto will start your integration using JBang + +### Test the Popular Books Endpoint + +```bash +curl http://localhost:8080/books/popular +``` + +You should receive a JSON array with popular books, showing their titles and authors: + +```json +[ + { + "title": "Frankenstein; or, the modern prometheus", + "authors": [ + { + "id": 3761, + "name": "Shelley, Mary Wollstonecraft" + } + ] + }, + { + "title": "The City of God, Volume I", + "authors": [ + { + "id": 18428, + "name": "Augustine, Saint, Bishop of Hippo" + }, + { + "id": 1101993, + "name": "Augustine, of Hippo, Saint" + } + ] + }, + { + "title": "Wuthering Heights", + "authors": [ + { + "id": 151, + "name": "Brontë, Emily" + } + ] + } + // ... more books +] +``` + +## Key Concepts + +### Apache Camel REST DSL + +The REST DSL (Domain Specific Language) in Apache Camel provides a declarative way to define REST APIs. It allows you to specify REST endpoints, their operations, parameters, and responses in a structured format that Camel uses to expose HTTP endpoints. + +**Key characteristics:** +- Declarative API definition separate from implementation logic +- Automatic HTTP endpoint generation +- Support for multiple REST components (platform-http, netty-http, servlet, etc.) +- Integration with OpenAPI specifications + +[Learn more about Apache Camel REST DSL](https://camel.apache.org/manual/rest-dsl.html) + +### Kaoto REST Editor + +Kaoto's REST Editor provides: +- **Tree view** of your complete REST API structure +- **Visual endpoint management** - add/edit/delete operations without YAML +- **Configuration forms** with validation and documentation +- **Quick actions** for adding operations and generating routes +- **Real-time sync** with Canvas and Code views + +### Direct Component + +The Direct component in Apache Camel provides direct, synchronous invocation of routes. It's commonly used to separate REST endpoint definitions from their implementation logic, allowing routes to be reusable and testable. + +**Key characteristics:** +- Synchronous, in-memory communication between routes +- No network overhead +- Ideal for internal route-to-route communication +- Supports request-reply pattern + +[Learn more about Camel Direct Component](https://camel.apache.org/components/latest/direct-component.html) + +### Adding Operations to Existing REST Blocks + +When extending an API, you can add operations to existing REST blocks: +- Operations within the same REST block share configuration +- Use the same REST block for related endpoints (e.g., all `/books/*` paths) +- This keeps your API structure organized and maintainable + +However, create separate REST blocks when you need different base paths, different configurations, or want to organize endpoints by distinct domains (e.g., `/books` vs `/authors`). + +### JSONPath for Data Transformation + +JSONPath is a query language for JSON, similar to XPath for XML. In Camel, the JSONPath language allows you to extract and transform data from JSON messages. + +**Key capabilities:** +- Extract specific fields from JSON responses +- Transform nested data structures +- Select multiple elements with wildcards (`*`) +- Combine multiple fields (`['title', 'authors']`) + +[Learn more about Camel JSONPath](https://camel.apache.org/components/latest/languages/jsonpath-language.html) + +### JSON Marshalling + +The `marshal` EIP (Enterprise Integration Pattern) in Apache Camel converts message bodies from one format to another. When used with the JSON data format, it serializes Java objects or other data structures into JSON format. + +**Key capabilities:** +- Converts Java objects to JSON +- Supports pretty printing for readable output +- Handles complex data structures automatically +- Can be configured with various options (include/exclude fields, date formats, etc.) + +[Learn more about Camel Marshal EIP](https://camel.apache.org/components/latest/eips/marshal-eip.html) +[Learn more about JSON Data Format](https://camel.apache.org/components/latest/dataformats/json-jackson-dataformat.html) + +## Summary + +This documentation demonstrated: + +1. ✅ Using Kaoto's REST Editor to manage REST endpoints visually +2. ✅ Adding a new GET endpoint using Kaoto's tree view and forms +3. ✅ Duplicating and reusing steps from existing routes +4. ✅ Implementing route logic using Kaoto's Canvas and component catalog +5. ✅ Using JSONPath for data extraction +6. ✅ Formatting JSON output with marshalling +7. ✅ Testing the new endpoint diff --git a/content/docs/rest/03_rest_editor/add-operation-modal.png b/content/docs/rest/03_rest_editor/add-operation-modal.png new file mode 100644 index 00000000..85a7ada7 Binary files /dev/null and b/content/docs/rest/03_rest_editor/add-operation-modal.png differ diff --git a/content/docs/rest/03_rest_editor/duplicate-component.png b/content/docs/rest/03_rest_editor/duplicate-component.png new file mode 100644 index 00000000..e291f206 Binary files /dev/null and b/content/docs/rest/03_rest_editor/duplicate-component.png differ diff --git a/content/docs/rest/03_rest_editor/final-route.png b/content/docs/rest/03_rest_editor/final-route.png new file mode 100644 index 00000000..219cee85 Binary files /dev/null and b/content/docs/rest/03_rest_editor/final-route.png differ diff --git a/content/docs/rest/03_rest_editor/new-route-created.png b/content/docs/rest/03_rest_editor/new-route-created.png new file mode 100644 index 00000000..0577dc90 Binary files /dev/null and b/content/docs/rest/03_rest_editor/new-route-created.png differ diff --git a/content/docs/rest/03_rest_editor/rest-form.png b/content/docs/rest/03_rest_editor/rest-form.png new file mode 100644 index 00000000..d9cc314c Binary files /dev/null and b/content/docs/rest/03_rest_editor/rest-form.png differ diff --git a/content/docs/rest/_index.md b/content/docs/rest/_index.md index 94ad9057..3dba81dd 100644 --- a/content/docs/rest/_index.md +++ b/content/docs/rest/_index.md @@ -1,41 +1,96 @@ --- -title: "Rest" -description: "update here" -date: 2026-03-25 +title: "REST DSL" +description: "Build REST APIs with Apache Camel using different approaches in Kaoto" +date: 2026-03-31 weight: 5 -draft: true --- -Some instructions: +## Overview -1. All the text and references should be written in this index file +The REST DSL (Domain Specific Language) in Apache Camel provides a powerful way to define REST APIs. Kaoto offers multiple approaches to work with REST DSL, each suited for different workflows and preferences. -2. You can add sub-folders (ex. in manual folder) and inside add index.md +This guide demonstrates two distinct approaches to building REST APIs with Kaoto: -3. The featured image for the main folder (ex.metadata) should be saved as featured.png +1. **[API-First Approach](01_api_first/)** - Link OpenAPI specifications at runtime +2. **[Code-First Approach](02_code_first/)** - Generate endpoints from OpenAPI using the REST Import Wizard or **[create endpoints manually from scratch using the visual REST Editor](03_rest_editor/)** -4. Example of useful shortcodes for image-code toggle, images and youtube videos: +Each approach builds a REST API that fetches books from Project Gutenberg via RapidAPI and generates AI-powered summaries using the Apache Camel OpenAI component. -{{< img-toggle src="./partial-route.webp" lang="yaml" >}} -- route: - id: route-2573 - from: - id: from-3280 - uri: file-watch - parameters: - path: /tmp/tutorial/ - recursive: false - steps: - - log: - message: Detected ${header.CamelFileEventType} on file ${header.CamelFileName} - at ${header.CamelFileLastModified} -{{< /img-toggle >}} +## Prerequisites -{{< figure src="dm-04-01-icon-opt.png" alt="Opt icon for optional field" caption="Opt icon for optional field" class="image" >}} +Before starting any of the approaches, ensure you have: -{{< youtube id="nuzl3p986Mc" class="video" title="DataMapper Expansion Panels Demo" >}} +- **VS Code** installed - [Download here](https://code.visualstudio.com/download) +- **Kaoto VS Code extension** - See the [installation guide](../installation/) +- **RapidAPI account and API key** - Sign up at [RapidAPI](https://rapidapi.com/) and subscribe to the [Project Gutenberg Free Books API](https://rapidapi.com/help-lQ_hVT8W5/api/project-gutenberg-free-books-api1) +- **Camel catalog** - This documentation was created with Camel version 4.18.0, though other versions and distributions are available -5. Use markdown features as you want and have fun! +### Additional Prerequisites for Code-First and REST Editor -6. Once finished, update the description, date and delete draft: true \ No newline at end of file +- **Ollama** installed and running - [Installation guide](https://ollama.com/download) +- **Granite 4 model** pulled in Ollama - Run `ollama pull granite4:tiny-h` ([Granite 4 on Ollama](https://ollama.com/library/granite4)) + +## Shared Resources + +The API-first and code-first approaches use the same OpenAPI specification: + +**[Download book-summary-api.openapi.yaml](./book-summary-api.openapi.yaml)** + +Save this file to your workspace folder before starting the API-first or code-first examples. The REST Editor approach creates endpoints from scratch without OpenAPI. + +## Comparison of Approaches + +| Aspect | API-First | Code-First | +|--------|-----------|----------------|-------------| +| **Workflow** | Link OpenAPI spec | Generate + Visual design | +| **OpenAPI Usage** | Runtime link (required) | Import wizard (not needed at runtime) or create from scratch | +| **Best For** | API contract enforcement | Learning, prototyping | +| **UI Interaction** | Minimal | Moderate | +| **Examples** | `/books/{id}/fun-extract` | `/books/{id}/fun-extract` + `/books/popular` | + +## Choose Your Approach + +### [1. API-First Approach](01_api_first/) + +**Best for**: Teams with strict API contracts, when the OpenAPI spec is the source of truth, or when you need runtime flexibility to update the API by changing the spec. + +**What you'll build**: A REST endpoint that fetches book summaries from Project Gutenberg by linking an OpenAPI specification. + +**Key characteristic**: The OpenAPI file must be present at runtime - Camel reads it to create endpoints. The OpenAPI file is the source of truth. + +--- + +### [2. Code-First Approach](02_code_first/) + +**Best for**: Rapid prototyping without OpenAPI available. + +**What you'll build**: The same REST endpoint as API-First, but with added AI-powered fun extracts using OpenAI, generated from the OpenAPI spec. + +**Key characteristic**: OpenAPI can be used only during development - endpoints are generated into your route file or create from scratch. The Camel route file is the source of truth. + +## Key Concepts + +### REST DSL + +Camel's domain-specific language for defining REST APIs. It provides a declarative way to specify REST endpoints, their operations, and how they map to Camel routes. + +[Learn more about Apache Camel REST DSL](https://camel.apache.org/manual/rest-dsl.html) + +### OpenAPI Specification + +A standard format for describing REST APIs. Kaoto can import OpenAPI specifications to automatically generate REST DSL definitions. + +[Learn more about OpenAPI and Camel](https://camel.apache.org/components/latest/others/openapi-java.html) + +### Direct Routes + +Reusable route components that can be called from REST endpoints. They separate the REST API definition from the implementation logic, providing synchronous in-memory communication between routes. + +[Learn more about Camel Direct Component](https://camel.apache.org/components/latest/direct-component.html) + +### REST Configuration + +Global settings that apply to all REST endpoints in your integration, such as the HTTP component, port, CORS settings, and binding mode. + +[Learn more about REST Configuration](https://camel.apache.org/manual/rest-dsl.html#_rest_configuration) \ No newline at end of file diff --git a/content/docs/rest/book-summary-api.openapi.yaml b/content/docs/rest/book-summary-api.openapi.yaml new file mode 100644 index 00000000..5d6e8d08 --- /dev/null +++ b/content/docs/rest/book-summary-api.openapi.yaml @@ -0,0 +1,46 @@ +openapi: 3.0.0 +info: + title: Book Summarization API + version: 1.0.0 + description: AI-powered book summaries using Project Gutenberg and OpenAI + +servers: + - url: http://localhost:8080 + description: Local development server + +paths: + /books/{id}/fun-extract: + get: + operationId: getBookFunExtract + summary: Get AI-generated fun extract of a book + description: Fetches a book from Project Gutenberg and generates an AI extract using OpenAI + parameters: + - name: id + in: path + required: true + description: Project Gutenberg book ID (e.g., 11 for Alice's Adventures in Wonderland) + schema: + type: integer + example: 11 + responses: + '200': + description: Book fun extract generated successfully + content: + application/json: + schema: + type: object + properties: + bookId: + type: integer + example: 11 + title: + type: string + example: "Alice's Adventures in Wonderland" + summary: + type: string + example: "A whimsical tale of a young girl who falls down a rabbit hole into a fantasy world populated by peculiar creatures with a funny twist." + '404': + description: Book not found in Project Gutenberg + '500': + description: Server error during processing + \ No newline at end of file