Fix #542: add a Couchbase source Kamelet - #3007
Merged
Merged
Conversation
The catalog had couchbase-sink but nothing on the consuming side, even though camel-couchbase supports both. This adds the missing half. The component polls a bucket in one of two modes and the Kamelet exposes both: an N1QL statement, which is the default, or a MapReduce view selected with designDocumentName and viewName when useView is true. Connection and credential properties mirror couchbase-sink exactly, including the connectionString escape hatch, so the pair reads the same way. Marked Preview, no Citrus test: exercising it needs a live Couchbase and there is no Couchbase container in the project's Citrus toolchain. Verified with `camel run` against the real component -- the Couchbase SDK initialises and begins bootstrapping from the configured host, the route reports "Routes startup (total:1 started:1 kamelets:1)" and there are zero unknown-option or endpoint-resolution errors; it then simply cannot reach a cluster that is not there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tz352mt7yzGWLfvYTBo2Dk
This was referenced Sep 7, 2026
oscerd
added a commit
that referenced
this pull request
Sep 7, 2026
Follow-up to #3007, which shipped the Kamelet without a test because there was no Couchbase container in the toolchain. There is one -- it just needs setting up by hand. Citrus 5.0.0 has no built-in Couchbase container type, so this uses the generic container with couchbase/server:community-7.6.2. Three details were not optional: - Ports are bound one-to-one. The Couchbase SDK bootstraps from the management port and then reconnects using the addresses the cluster advertises, so a remapped host port leaves the client unable to reach the data service. - The wait strategy needs a full-line regex. Testcontainers matches log wait patterns against the whole line, so "Starting Couchbase Server" never matches and the container times out after five minutes. - initCluster.groovy avoids Groovy GStrings entirely. Citrus resolves dollar-brace expressions in these scripts as its own test variables, so a GString fails with "Unknown variable". The script initialises the cluster, creates a bucket, adds a primary index and seeds one document over plain HTTP, so the test module needs no Couchbase SDK on its classpath. It polls for the management port itself because the container logs its startup line well before that port serves requests. The statement in application.properties is "SELECT META().id AS __id, * FROM _default" rather than the more obvious "SELECT * FROM <bucket>". Both parts matter: CouchbaseConsumer skips any row without the __id alias, and it runs the query in the bucket scope, so the keyspace is the collection. Passes locally in about 35 seconds: Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 -- in CouchbaseIT SUCCESS (38088ms) couchbase-source-route-test Claude-Session: https://claude.ai/code/session_01Tz352mt7yzGWLfvYTBo2Dk Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
oscerd
added a commit
that referenced
this pull request
Sep 7, 2026
The example shipped in #3007 -- SELECT * FROM `travel-sample` LIMIT 10 -- does not work, and fails in the worst way: the source polls happily and emits nothing. Two requirements, both found by running the Kamelet against a live cluster while writing the integration test in #3008: CouchbaseConsumer reads row.getString("__id") and skips any row without that field, logging a warning rather than failing. A query that does not alias the document id as __id therefore produces no exchanges at all. The consumer runs the query through scope.query(...), so the keyspace resolves as <bucket>._default.<what-you-wrote>. Naming the bucket gives <bucket>._default.<bucket> and fails with "Keyspace not found"; the collection, normally _default, is what belongs there. The example now matches what the integration test actually uses, and the description states both requirements so the next person does not have to rediscover them from a silent no-op. Claude-Session: https://claude.ai/code/session_01Tz352mt7yzGWLfvYTBo2Dk Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #542.
The catalog shipped
couchbase-sinkbut nothing on the consuming side, even thoughcamel-couchbasesupports both. This adds the missing half.Two polling modes, both exposed
The component's own description is "Query Couchbase databases using SQL (N1QL) queries or MapReduce Views with a poll strategy", and the Kamelet covers both:
statementproperty runs against the bucket on each polluseView: trueand select it withdesignDocumentName/viewNameRather than pick one and hide the other, the description says plainly which properties belong to which mode, since
designDocumentNameandviewNameare inert unlessuseViewis on.Consistency with the sink
Connection and credential properties mirror
couchbase-sinkexactly — same names (protocol,couchbaseHostname,couchbasePort,bucket,username,password), sameformat: passwordand credentials descriptor on the password, and the sameconnectionStringescape hatch with the same wording. Someone configuring the pair should not have to learn two vocabularies.The source-only additions are the query options the consumer actually reads:
statement,useView,designDocumentName,viewName,fullDocument,limit,skip,descending, anddelayfor the poll interval. The sink-onlystartingId/autoStartIdare deliberately absent — they configure insert id generation and have no meaning on a consumer.Verification
script/validatorreports no errors,script/generatoradds thenav.adocentry, andmvn clean installpasses with tests from the repository root.Parameter binding checked against the real component with
camel run. The Couchbase SDK initialises and starts bootstrapping from the configured host:with zero unknown-option or endpoint-resolution errors — it then simply cannot reach a cluster that is not running. A mistyped parameter would have failed before any of that.
No Citrus test: exercising this needs a live Couchbase and the project's Citrus/Testcontainers toolchain has no Couchbase container, so it ships
Previewwithoutkamelet.verified=true. Happy to add one in a follow-up if there is an image the project is willing to depend on.The icon is the existing Couchbase icon reused from
couchbase-sink, so the pair renders consistently.Claude Code on behalf of Andrea Cosentino