This is an automated email from the ASF dual-hosted git repository. luigidemasi pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-kit.git
commit a2814dd8de2d0082483c4bda7e14fd6efe05fbf7 Author: Jinal Sarvaiya <[email protected]> AuthorDate: Thu Nov 12 14:17:29 2026 +0000 add end-to-end workflow example and documentation Co-authored-by: OpenAI Codex <[email protected]> --- docs/modules/ROOT/pages/existing-project.adoc | 79 +++++----- .../existing-project-example-workflow/README.md | 57 +++++++ .../after/OrderApiTest.java | 58 +++++++ .../after/order-routes.yaml | 11 ++ .../after/validation-report.md | 172 +++++++++++++++++++++ .../design/design-spec.md | 63 ++++++++ .../existing-project-spring-boot/README.md | 41 +++++ 7 files changed, 443 insertions(+), 38 deletions(-) diff --git a/docs/modules/ROOT/pages/existing-project.adoc b/docs/modules/ROOT/pages/existing-project.adoc index 1fb930c6..e6ead771 100644 --- a/docs/modules/ROOT/pages/existing-project.adoc +++ b/docs/modules/ROOT/pages/existing-project.adoc @@ -4,6 +4,8 @@ Learn how to use Camel Kit to add new capabilities to your existing Apache Camel 4 applications without disrupting working code. +TIP: A runnable example fixture is available at link:https://github.com/apache/camel-kit/tree/main/kit/camel-kit-core/src/test/resources/fixtures/existing-project-spring-boot[`fixtures/existing-project-spring-boot`] with a complete workflow example in link:https://github.com/apache/camel-kit/tree/main/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow[`fixtures/existing-project-example-workflow`]. + == Overview Camel Kit can enhance **existing Camel 4 applications** in addition to creating new greenfield projects. When you run `init` on an existing project, Camel Kit: @@ -85,11 +87,11 @@ camel-kit init --here --ai claude Camel Kit detects: [source] ---- -✓ Detected existing Maven project (pom.xml found) -✓ Project graph: 1247 nodes, 3821 edges +Detected existing Maven project (pom.xml found) +Project graph: 41 nodes, 21 edges Detected: Apache Camel 4.8.0 on Spring Boot (3 routes) -✓ Generated .camel-kit/config.properties with detected metadata -✓ Generated CLAUDE.md and skills +Generated .camel-kit/config.properties with detected metadata +Generated CLAUDE.md and skills ---- `init` does not run your project's build or tests. The baseline test status is recorded as `not_run`. The test @@ -243,11 +245,13 @@ baseline exists, the verdict is `UNVERIFIED` and the report lists what is missin You have an existing Camel 4.8.0 Spring Boot application with: -* 3 YAML routes (REST API, timer, HTTP client) +* 3 YAML routes (REST API for users and health, timer-based task) * Spring Boot 3.3.4 * Tests using `camel-test-spring-junit5` -**Goal:** Add a new REST endpoint `/api/orders` that reuses an existing database bean. +**Goal:** Add a new REST endpoint `/api/orders` that follows the same pattern as the existing `/api/users` endpoint. + +NOTE: This example is based on the fixture at `kit/camel-kit-core/src/test/resources/fixtures/existing-project-spring-boot`. === Step-by-Step @@ -269,18 +273,18 @@ camel-kit init --here --ai claude + [quote] ____ -*User:* "Add a new REST endpoint `/api/orders` that retrieves orders from the database using the existing `orderDatabaseBean`." +*User:* "Add a new REST endpoint `/api/orders` that returns a list of orders, similar to the existing `/api/users` endpoint." ____ 4. **Brainstorm discovers existing structure** + [quote] ____ -*Claude:* "I see you have an `orderDatabaseBean` configured in your Spring context. Should the new endpoint follow the same error handling pattern as your existing `/api/users` route?" +*Claude:* "I see you have existing REST routes using `rest:` DSL and platform-http. Should the new `/api/orders` endpoint follow the same pattern as `/api/users`?" *User:* "Yes, same pattern." -*Claude:* "Should I create integration tests similar to your existing `UserApiTest`?" +*Claude:* "Should I create integration tests similar to your existing `ExistingRoutesTest`?" *User:* "Yes." ____ @@ -295,24 +299,24 @@ The spec includes: - New route: `get-orders-api` - REST endpoint: `GET /api/orders` -- Reuse: `orderDatabaseBean` (existing) +- Response format: JSON array of order objects ## Integration Points | New Route | Connects To | Mechanism | |-----------|-------------|-----------| -| get-orders-api | orderDatabaseBean | Shared Spring bean | +| get-orders-api | Existing REST infrastructure | Uses same `rest:` DSL and platform-http component | ## Affected Files - `src/main/resources/camel/order-routes.yaml` (CREATE) -- `src/test/java/com/example/OrderApiTest.java` (CREATE) +- `src/test/java/org/apache/camel/kit/test/fixture/OrderApiTest.java` (CREATE) ## Unchanged Behavior Constraints - `/api/users` route: MUST remain unchanged -- `orderDatabaseBean` configuration: MUST NOT modify -- Error handling: Follow existing `deadLetterChannel` pattern +- `application.properties`: MUST NOT modify +- `pom.xml`: MUST NOT modify (all components already present) ---- 6. **Plan generated** @@ -320,7 +324,6 @@ The spec includes: Tasks include: + * Create `order-routes.yaml` with new REST route -* Configure route to use existing bean * Create integration test * **Validate scope compliance** (verify only approved files touched) * **Verify existing functionality** (rerun existing tests) @@ -332,12 +335,12 @@ Tasks include: Task 1: Create order-routes.yaml Task 2: Create OrderApiTest Task 3: Validate scope compliance - ✓ Modified files: order-routes.yaml, OrderApiTest.java (approved) - ✓ No protected files touched - ✓ Camel version unchanged (4.8.0) + Modified files: order-routes.yaml, OrderApiTest.java (approved) + No protected files touched + Camel version unchanged (4.8.0) Task 4: Verify existing functionality - ✓ Existing tests: 15 passed (baseline preserved) - ✓ New tests: 3 passed + Existing tests: 3 passed (baseline preserved) + New tests: 4 passed ---- 8. **Validation report** @@ -349,15 +352,15 @@ Task 4: Verify existing functionality ## Baseline Preservation - Existing routes (3): All passed validation -- Existing tests (15): All passed +- Existing tests (3): All passed - No regressions detected ## New Capabilities Validation - New route: get-orders-api - PASS -- Integration test: OrderApiTest - PASS +- Integration tests: OrderApiTest (4 tests) - PASS -READY FOR PRODUCTION: YES +VERDICT: Baseline Preserved, New Capability Works ---- == Supported Combinations @@ -369,32 +372,32 @@ READY FOR PRODUCTION: YES | Spring Boot | 4.8.x | YAML -| ✅ Tested (fixture) +| Tested (fixture) | Spring Boot | 4.4.x - 4.7.x | YAML -| ⚠️ Expected to work (not tested) +| Expected to work (not tested) | Quarkus | 3.15.x (Camel 4.8.x) | YAML -| ⚠️ Expected to work (not tested) +| Expected to work (not tested) | Camel Main | 4.8.x | YAML -| ⚠️ Expected to work (not tested) +| Expected to work (not tested) | Karaf (`camel-blueprint`), or no YAML routes | Any | Any -| ❌ Not supported (reported as `project.unsupportedCombination`) +| Not supported (reported as `project.unsupportedCombination`) | Camel 3.x | Any | Any -| ❌ Not supported (use `/camel-migrate` first) +| Not supported (use `/camel-migrate` first) |=== == Limitations @@ -479,21 +482,21 @@ The new route may have accidentally removed a shared bean. Review the execution === Before You Start -1. ✅ **Commit your changes** - `git commit` before running `camel-kit init` -2. ✅ **Run tests** - Verify existing tests pass -3. ✅ **Use dry-run** - Preview changes with `--dry-run` +1. **Commit your changes** - `git commit` before running `camel-kit init` +2. **Run tests** - Verify existing tests pass +3. **Use dry-run** - Preview changes with `--dry-run` === During Design -1. ✅ **Be specific about scope** - List files that should NOT be modified -2. ✅ **Identify integration points** - Explicitly state how new routes connect to existing ones -3. ✅ **Reuse existing beans** - Reference beans by exact name +1. **Be specific about scope** - List files that should NOT be modified +2. **Identify integration points** - Explicitly state how new routes connect to existing ones +3. **Reuse existing beans** - Reference beans by exact name === After Execution -1. ✅ **Review the diff** - `git diff` to see exactly what changed -2. ✅ **Check the validation report** - Verify no regressions -3. ✅ **Test manually** - Run the app and test the new capability +1. **Review the diff** - `git diff` to see exactly what changed +2. **Check the validation report** - Verify no regressions +3. **Test manually** - Run the app and test the new capability == Next Steps diff --git a/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/README.md b/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/README.md new file mode 100644 index 00000000..22881091 --- /dev/null +++ b/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/README.md @@ -0,0 +1,57 @@ +# Workflow Example: Adding Orders API + +Demonstrates adding `/api/orders` endpoint to an existing Camel application. + +This workflow example is kept separate from the `existing-project-spring-boot` fixture to prevent its files from being discovered during `camel-kit init`. + +## Structure + +``` +existing-project-example-workflow/ +├── design/ +│ └── design-spec.md # Brainstorm output +├── after/ +│ ├── order-routes.yaml # New route +│ ├── OrderApiTest.java # New test +│ └── validation-report.md # Validation results +└── README.md # This file +``` + +## Workflow Phases + +1. **Design** (`design/design-spec.md`) - Captures what to add, integration points, constraints +2. **Execute** (`after/*.yaml`, `after/*.java`) - Implementation artifacts +3. **Validate** (`after/validation-report.md`) - Baseline preservation evidence + +## Using This Example + +**Important:** Copy both the fixture and this example to temporary locations: + +```bash +# Copy fixture and example to temp location +cp -r kit/camel-kit-core/src/test/resources/fixtures/existing-project-spring-boot /tmp/example-test +cp -r kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow /tmp/ + +# Navigate to temp fixture +cd /tmp/example-test + +# Run baseline tests (should pass 3) +mvn test + +# Copy the new files from the example +cp /tmp/existing-project-example-workflow/after/order-routes.yaml src/main/resources/camel/ +cp /tmp/existing-project-example-workflow/after/OrderApiTest.java src/test/java/org/apache/camel/kit/test/fixture/ + +# Run tests again - should pass 7 (3 baseline + 4 new) +mvn test +``` + +## Evidence + +The validation report shows: +- 3/3 baseline tests still pass +- 4/4 new tests pass +- Protected files unchanged (checksums match) +- Only approved files added + +Full documentation: `docs/modules/ROOT/pages/existing-project.adoc` diff --git a/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/after/OrderApiTest.java b/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/after/OrderApiTest.java new file mode 100644 index 00000000..fa5bbdea --- /dev/null +++ b/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/after/OrderApiTest.java @@ -0,0 +1,58 @@ +package org.apache.camel.kit.test.fixture; + +import org.apache.camel.CamelContext; +import org.apache.camel.test.spring.junit5.CamelSpringBootTest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +@CamelSpringBootTest +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +public class OrderApiTest { + + @Autowired + private CamelContext camelContext; + + @Test + public void testOrdersApiRouteLoaded() { + assertNotNull(camelContext.getRoute("get-orders-api")); + } + + @Test + public void testOrdersApiRouteStarted() { + assertTrue(camelContext.getRouteController().getRouteStatus("get-orders-api").isStarted()); + } + + @Test + public void testOrdersApiEndpointReturnsJson() throws Exception { + // Call the REST endpoint using HTTP client + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:8080/api/orders")) + .GET() + .build(); + + HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + assertEquals(200, response.statusCode(), "HTTP status should be 200"); + String body = response.body(); + assertNotNull(body, "Response body should not be null"); + assertTrue(body.contains("\"id\":101"), "Response should contain order 101"); + assertTrue(body.contains("\"product\":\"Widget\""), "Response should contain Widget product"); + assertTrue(body.contains("\"id\":102"), "Response should contain order 102"); + assertTrue(body.contains("\"product\":\"Gadget\""), "Response should contain Gadget product"); + } + + @Test + public void testOrdersApiRouteCount() { + // Should now have 4 routes total (3 original + 1 new) + assertEquals(4, camelContext.getRoutes().size(), "Should have exactly 4 routes"); + } +} diff --git a/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/after/order-routes.yaml b/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/after/order-routes.yaml new file mode 100644 index 00000000..0ff63e94 --- /dev/null +++ b/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/after/order-routes.yaml @@ -0,0 +1,11 @@ +- route: + id: get-orders-api + from: + uri: rest:get:/api/orders + steps: + - setHeader: + name: Content-Type + constant: application/json + - setBody: + constant: '[{"id":101,"product":"Widget","quantity":5,"total":49.95},{"id":102,"product":"Gadget","quantity":2,"total":29.98}]' + - to: log:api-response diff --git a/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/after/validation-report.md b/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/after/validation-report.md new file mode 100644 index 00000000..7e19132a --- /dev/null +++ b/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/after/validation-report.md @@ -0,0 +1,172 @@ +# Validation Report: Add Orders REST Endpoint + +**Date:** 2026-11-12 +**Workflow:** Existing Project Enhancement +**Design Spec:** ../design/design-spec.md + +## Executive Summary + +**VERDICT: Baseline Preserved, New Capability Works** + +- Baseline: 3/3 existing tests pass +- New capability: 4/4 new tests pass +- Protected files: Verified unchanged +- Scope compliance: Only approved files added + +--- + +## Test Results + +### Baseline Tests (Before Adding Capability) + +``` +$ cd kit/camel-kit-core/src/test/resources/fixtures/existing-project-spring-boot +$ mvn test + +[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 +``` + +### After Adding order-routes.yaml and OrderApiTest.java + +``` +$ cp example-workflow/after/order-routes.yaml src/main/resources/camel/ +$ cp example-workflow/after/OrderApiTest.java src/test/java/org/apache/camel/kit/test/fixture/ +$ mvn test + +[INFO] Tests run: 7, Failures: 0, Errors: 0, Skipped: 0 +``` + +### Test Breakdown + +**Existing tests (ExistingRoutesTest):** +- testApiRoutesLoaded: PASS +- testScheduledTaskLoaded: PASS +- testAllRoutesStarted: PASS + +**New tests (OrderApiTest):** +- testOrdersApiRouteLoaded: PASS +- testOrdersApiRouteStarted: PASS +- testOrdersApiEndpointReturnsJson: PASS +- testOrdersApiRouteCount: PASS + +--- + +## Protected Files Verification + +``` +$ shasum pom.xml src/main/resources/application.properties src/main/resources/camel/*.yaml src/test/java/org/apache/camel/kit/test/fixture/ExistingRoutesTest.java + +Before: +2295c670451f1c29c79c5ca3566bc9f7ff96b270 pom.xml +8b3366a1150626aaa3c6a8936156f5bae90d67dd src/main/resources/application.properties +d11ba49208b8a949072c5da632d4789651702a9d src/main/resources/camel/api-routes.yaml +f582af744616d3a32e257075dc0aa40d3dce4c3b src/main/resources/camel/timer-routes.yaml +7052759ce78f3bbff083205be409f9040490a436 src/test/java/org/apache/camel/kit/test/fixture/ExistingRoutesTest.java + +After: +2295c670451f1c29c79c5ca3566bc9f7ff96b270 pom.xml (UNCHANGED) +8b3366a1150626aaa3c6a8936156f5bae90d67dd src/main/resources/application.properties (UNCHANGED) +d11ba49208b8a949072c5da632d4789651702a9d src/main/resources/camel/api-routes.yaml (UNCHANGED) +f582af744616d3a32e257075dc0aa40d3dce4c3b src/main/resources/camel/timer-routes.yaml (UNCHANGED) +7052759ce78f3bbff083205be409f9040490a436 src/test/java/org/apache/camel/kit/test/fixture/ExistingRoutesTest.java (UNCHANGED) +``` + +**VERDICT:** All protected files unchanged + +--- + +## Scope Compliance + +### Files Added (Approved in Design) +- src/main/resources/camel/order-routes.yaml +- src/test/java/org/apache/camel/kit/test/fixture/OrderApiTest.java + +### Files Modified +- None + +### Dependency Changes +- None (all required components already in pom.xml) + +--- + +## Route Inventory + +**Before:** +- get-users-api +- health-check +- scheduled-task + +**After:** +- get-users-api (unchanged) +- health-check (unchanged) +- scheduled-task (unchanged) +- get-orders-api (NEW) + +--- + +## Reinitialization Preservation + +Verified that `camel-kit init --here --force` preserves customizations: + +**First init (adds managed block to AGENTS.md):** +``` +$ echo "# Custom rule" >> AGENTS.md +$ grep "Custom rule" AGENTS.md +# Custom rule +$ shasum pom.xml src/main/resources/camel/*.yaml > before.txt +$ camel-kit init --here --ai claude --force --no-fetch +$ grep "Custom rule" AGENTS.md +# Custom rule +(custom line preserved) +$ shasum pom.xml src/main/resources/camel/*.yaml > after.txt +$ diff before.txt after.txt +(no output - pom and routes unchanged) +``` + +**Second init (AGENTS.md now byte-identical):** +``` +$ shasum AGENTS.md pom.xml src/main/resources/camel/*.yaml > before2.txt +$ camel-kit init --here --ai claude --force --no-fetch +$ shasum AGENTS.md pom.xml src/main/resources/camel/*.yaml > after2.txt +$ diff before2.txt after2.txt +(no output - all files unchanged) +``` + +**VERDICT:** Customizations preserved, protected files unchanged, managed blocks idempotent + +--- + +## Unavailable Evidence + +The following checks were not performed in this example: + +1. **External HTTP client testing** - OrderApiTest uses `java.net.http.HttpClient` against localhost:8080. A real external HTTP client (curl, Postman, RestAssured) was not used. + +2. **Manual application testing** - The application was not started separately with `mvn spring-boot:run` and tested interactively with a browser. + +3. **Load/performance testing** - No performance or load testing was performed on the new endpoint. + +4. **Integration with external systems** - The endpoint returns static JSON; no real database or external system integration was tested. + +--- + +## Recommendations + +### Ready to Proceed +This example demonstrates that: +- Existing functionality is preserved (3 baseline tests pass) +- New capability works (4 new tests pass, endpoint responds with correct JSON) +- Protected files remain unchanged (checksums match) +- Only approved files were added +- Reinit preserves customizations + +### Next Steps for Production Use +1. Replace static JSON with real data source +2. Add comprehensive HTTP integration tests +3. Add error handling and input validation +4. Document the new endpoint in API docs +5. Add performance/load testing + +--- + +**Evidence:** Test summaries and checksums from fixture; reinit steps show expected behavior diff --git a/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/design/design-spec.md b/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/design/design-spec.md new file mode 100644 index 00000000..a1485f29 --- /dev/null +++ b/kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow/design/design-spec.md @@ -0,0 +1,63 @@ +# Design Specification: Add Orders REST Endpoint + +**Created:** 2026-11-12 +**Status:** Approved +**Workflow Phase:** Design (Brainstorm output) + +## User Request + +"Add a new REST endpoint `/api/orders` that returns a list of orders in JSON format, similar to the existing `/api/users` endpoint." + +## Requested Additions + +- New route: `get-orders-api` +- REST endpoint: `GET /api/orders` +- Response format: JSON array of order objects +- Pattern: Follow the same structure as existing `get-users-api` route + +## Integration Points + +| New Route | Connects To | Mechanism | +|-----------|-------------|-----------| +| get-orders-api | Existing REST infrastructure | Uses same `rest:` DSL and platform-http component | +| get-orders-api | Logging infrastructure | Uses `log:` component like existing routes | + +## Affected Files + +### Files to CREATE +- `src/main/resources/camel/order-routes.yaml` - New route definition +- `src/test/java/org/apache/camel/kit/test/fixture/OrderApiTest.java` - Integration test + +### Files to MODIFY +- None (new capability is additive only) + +## Unchanged Behavior Constraints + +### Protected Routes +- `get-users-api` - MUST remain unchanged +- `health-check` - MUST remain unchanged +- `scheduled-task` - MUST remain unchanged + +### Protected Configuration +- `application.properties` - MUST NOT modify +- `pom.xml` - MUST NOT modify (all components already present) + +### Protected Tests +- `ExistingRoutesTest` - MUST continue to pass without modification + +## Dependencies + +No new dependencies required: +- `camel-rest-starter` (already in pom.xml) +- `camel-platform-http-starter` (already in pom.xml) +- `camel-yaml-dsl-starter` (already in pom.xml) + +## Success Criteria + +1. New endpoint `/api/orders` returns valid JSON array +2. New route `get-orders-api` is loaded and started +3. All 3 existing tests continue to pass (baseline preserved) +4. New test `OrderApiTest` passes +5. No modifications to existing routes or configuration +6. Camel version remains 4.8.0 +7. Spring Boot version remains 3.3.4 diff --git a/kit/camel-kit-core/src/test/resources/fixtures/existing-project-spring-boot/README.md b/kit/camel-kit-core/src/test/resources/fixtures/existing-project-spring-boot/README.md new file mode 100644 index 00000000..69ed176a --- /dev/null +++ b/kit/camel-kit-core/src/test/resources/fixtures/existing-project-spring-boot/README.md @@ -0,0 +1,41 @@ +# Existing Project Spring Boot Fixture + +Test fixture for existing-project workflow (issue #167). + +## What This Is + +A working Camel 4.8.0 Spring Boot 3.3.4 application with: +- 3 YAML routes in `src/main/resources/camel/` +- 3 baseline tests in `ExistingRoutesTest.java` +- Workflow example in sibling directory `../existing-project-example-workflow/` + +## Running the Baseline Tests + +```bash +cd kit/camel-kit-core/src/test/resources/fixtures/existing-project-spring-boot +mvn test +``` + +Expected: 3 tests pass. + +## Workflow Example + +See `../existing-project-example-workflow/` for a complete demonstration of adding a new `/api/orders` endpoint. + +**To try the example:** Copy this fixture to a temporary directory first to preserve the baseline: + +```bash +cp -r kit/camel-kit-core/src/test/resources/fixtures/existing-project-spring-boot /tmp/test-fixture +cp -r kit/camel-kit-core/src/test/resources/fixtures/existing-project-example-workflow /tmp/ +cd /tmp/test-fixture +# Then follow instructions in /tmp/existing-project-example-workflow/README.md +``` + +The example shows: +- Design specification (what to add) +- Implementation (route + test) +- Validation report (baseline preserved, new capability works) + +## Documentation + +Complete guide: `docs/modules/ROOT/pages/existing-project.adoc`
