davsclaus opened a new pull request, #28393:
URL: https://github.com/apache/camel/pull/28393
_Claude Code on behalf of davsclaus_
This group adds the catalog body types (CAMEL-24961) for eleven database
components: jpa, sql-stored, mybatis, mybatis-bean, jooq, pgevent,
pg-replication-slot, duckdb, clickhouse, drill and kudu. Each change is only an
`@BodyTypes` annotation on the Endpoint, plus the JSON it generates and the
catalog copy. Three doc pages had their body text corrected.
**What the catalog says now**
| Component | Consumer | Producer input | Producer output |
|---|---|---|---|
| jpa | one entity per message; a query that selects columns gives an Object
array or one value | the entity to merge, persist or remove (a List or an array
needs entityType `java.util.List`); the key with findEntity; not read with a
query, whose parameters come from the `parameters` option or the
CamelJpaParameters header | the managed entity that merge returns; unchanged
with usePersist; the entity or null with findEntity; a query gives a List, its
one result with singleResult, or the update count as an Integer; outputTarget
keeps the body |
| sql-stored | | `any`: a `:#name` parameter reads a Map body, or else the
header; a List or an Iterator with batch; the template as text with
useMessageBodyForTemplate | a `Map` of the OUT and INOUT parameters, with
`#result-set-1` and `#update-count-1`; unchanged with noop, batch or
outputHeader |
| mybatis | one row per message as the statement maps it (a List of all rows
with useIterator=false) | the parameter, handed to MyBatis without conversion |
by statementType: SelectOne the row or null, SelectList a List; Insert, Update
and Delete keep the body, with the count in CamelMyBatisResult |
| mybatis-bean | | the argument of the method, converted by the bean binding
| what the method returns; a void method keeps the body |
| jooq | one `UpdatableRecord` of the entityType per row | a record for
NONE, an `org.jooq.Query` for EXECUTE, an `org.jooq.ResultQuery` for FETCH; not
read with the `query` option | unchanged; `org.jooq.Result` for FETCH |
| pgevent | the payload as a `String`, with the channel in a header | `any`,
converted to a String (under 8000 bytes) | unchanged |
| pg-replication-slot | `byte[]`: text for test_decoding, JSON for wal2json,
binary for pgoutput | | |
| duckdb | | the SQL as text, bytes, a stream or a file; a List of Maps for
INSERT; a File or a path for COPY | the row count as a `Long`; for QUERY a List
of Maps (a JSON String with resultFormat=JSON); a `Boolean` for PING |
| clickhouse | | the rows in the format of the `format` option, as text,
bytes, a stream or a file, or a List of objects registered on the Client; the
SQL for QUERY | unchanged, with the count in CamelClickHouseWrittenRows; a
`String` for QUERY; a `Boolean` for PING |
| drill | | `any`: the query is the CamelDrillQuery header | a List of Maps
of the rows |
| kudu | | a Map of one row for insert, update, upsert and delete; `any` for
scan and create_table, which take headers | unchanged; a List of Maps for scan |
**Checked at runtime.** Each component ran in throwaway tests that sent
text, bytes, a stream, a file, a Map, a POJO and no body, and logged the class
of the body after each step. The tests are not part of the PR. The databases
used:
- **Embedded:** H2 for jpa (OpenJPA) and mybatis; HSQLDB for jooq and the
sql-stored procedures; DuckDB.
- **Docker:**
- PostgreSQL 17 for pgevent and pg-replication-slot, with test_decoding
and pgoutput;
- ClickHouse 26.9;
- Apache Drill 1.22.0;
- a Kudu master and tablet server.
mybatis was run with InOnly and InOut. Not run:
- sql-stored: a procedure that returns a result set, `function=true`, an
INOUT parameter.
- clickhouse: a List of registered POJOs (the client could not read the
table schema from this server).
**Choices**
- mybatis has no default statementType, so the default output is `unknown`,
and every statement type is listed by option.
- The rows of the mybatis consumer and of SelectOne are `unknown`, because
the statement's resultType or resultMap decides their class.
- The javaType of a List of rows is `java.util.List<java.util.Map<String,
Object>>`, as for the AWS components.
**Doc fixes**
- mybatis-bean: the body is what the mapper method returns, not only the
result of a SELECT.
- mybatis: the result goes to the outputHeader header when that option is
set.
- jooq: the operations table said that NONE executes a query. NONE stores
the record.
**Bugs found, not fixed here.** The JIRAs, one per component, will follow.
- **mybatis:**
- With an InOut exchange, Insert, Update and Delete (and their List
variants) set the body to null instead of keeping it.
`MyBatisProducer.doProcessResult` uses `getOut()` and copies the body only with
outputHeader.
- An Insert with no body stores a row of NULLs, with no error.
- **jooq:**
- The `operation` enum of the catalog lists CONSUME, but `JooqOperation`
has no such value, so `operation=consume` fails.
- NONE with no body inserts an empty record.
- EXECUTE or FETCH with neither a body nor `query` fails with
`NoSuchMethodException: org.jooq.Query.<init>()`.
- **jpa:**
- A consumer whose query returns scalar values delivers nothing with the
default consumeLockEntity=true. Each row is skipped, with only a debug log.
- The page says the entity class is optional for a producer, but the path
is required.
- **sql-stored:**
- With batch=true, CamelSqlStoredUpdateCount sums the `executeBatch()`
counts, including SUCCESS_NO_INFO (-2), so 2 items gave -4.
- A single Map body with batch=true is iterated as map entries, and the
call fails with an unclear SQLException.
- **duckdb:**
- The `query` option is documented "for query when the message body is
empty", but it replaces a non-empty body too.
- COPY rejects a `java.nio.file.Path` and a byte[] body.
- Running a SELECT as execute, or DDL as query, gives a JDBC error with no
hint to change the operation.
- **clickhouse:**
- QUERY decodes the response as a UTF-8 String, so binary formats
(RowBinary, Native, Parquet) are corrupted.
- Inserting a List of Maps, or of POJOs that are not registered, fails
with a NullPointerException inside the client.
- CamelClickHouseReadRows is the number of rows scanned, not the number
returned.
- **pg-replication-slot:** the exchange id is the last received LSN, which
is not unique. The BEGIN and the first change of a transaction got the same id.
- **kudu:**
- No `operation` fails with a NullPointerException.
- A body that is not a Map fails with a NullPointerException ("rows" is
null).
- CamelKuduScanLimit as an Integer fails with a ClassCastException (a raw
`(Long)` cast).
- **drill:**
- No CamelDrillQuery header fails with `SQLException: Error while
executing SQL "null"`.
- On JDK 25 the Drill JDBC driver cannot connect (`PooledDirectByteBuf
cannot be cast to PooledUnsafeDirectByteBuf`) unless run with
`-Dio.netty.noUnsafe=false`.
Open PR #22358 changes code in camel-jooq, camel-mybatis and camel-sql, but
not the Endpoint classes or the generated files of this PR.
**Local checks**
- The 10 changed modules build, with no change to the generated files after
the build.
- The 14 catalog copies equal their modules.
- camel-catalog tests pass (1103).
- The Endpoint and Component DSLs regenerate with no change.
- camel-yaml-dsl-validator tests pass (295).
- camel-jbang-core tests pass (2424 and 238).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]