[
https://issues.apache.org/jira/browse/CAMEL-24131?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Claus Ibsen updated CAMEL-24131:
--------------------------------
Fix Version/s: 4.22.0
> camel-jpa: consumer with nativeQuery (no resultClass) and default
> consumeDelete fails to delete rows, causing endless reprocessing
> ----------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-24131
> URL: https://issues.apache.org/jira/browse/CAMEL-24131
> Project: Camel
> Issue Type: Bug
> Components: camel-jpa
> Reporter: Federico Mariani
> Assignee: Claus Ibsen
> Priority: Major
> Fix For: 4.22.0
>
>
> h3. Problem
> When a JPA consumer is configured with {{nativeQuery}} and no
> {{resultClass}}, results are returned as {{Object[]}} rows (see
> {{QueryBuilder.nativeQuery(String)}}). {{consumeDelete}} defaults to
> {{true}}, so {{JpaConsumer.createDeleteHandler()}} (JpaConsumer.java:451-480)
> returns:
> {code:java}
> (EntityManager em, Object entityBean, Exchange exchange) ->
> em.remove(entityBean);
> {code}
> {{EntityManager#remove}} requires a managed entity instance; calling it with
> an {{Object[]}} throws {{IllegalArgumentException}}. Unlike the
> {{@PreConsumed}}/{{@Consumed}} handlers, which guard with
> {{entityType.isInstance(entityBean)}} (JpaConsumer.java:435, 463), the
> {{consumeDelete}} handler has no such guard. {{lockEntity()}} even
> anticipates this exact case -- it treats a lock failure on an array as
> expected (JpaConsumer.java:374-376) -- but the delete path does not.
> h3. Impact
> The exchange is processed successfully by the route (the
> {{Processor.process(exchange)}} call succeeds), but the subsequent
> {{getDeleteHandler().deleteObject(...)}} call throws. Because this happens
> *after* successful processing, the row is never deleted from the database. On
> the next poll, the same native-query result set (same rows) is selected and
> reprocessed -- a poison-poll loop: duplicate downstream processing plus a
> logged/thrown error on every single poll, indefinitely.
> h3. How to reproduce
> {code:java}
> from("jpa://com.foo.MyEntity?nativeQuery=select * from MY_ENTITY where
> processed = false")
> .to("mock:result");
> {code}
> against a table with at least one matching row and no {{resultClass}}
> configured: the row is delivered to {{mock:result}} on every poll, and
> {{em.remove(Object[])}} throws each time.
> h3. Suggested fix
> Guard the default {{consumeDelete}} handler the same way the annotation-based
> handlers are guarded (e.g. skip/log when the result is not an instance of the
> configured entity type), or fail endpoint validation eagerly when
> {{nativeQuery}} is set without {{resultClass}} and {{consumeDelete=true}}.
> Found during a broader camel-jpa code review (July 2026).
> _Claude Code on behalf of Croway_
--
This message was sent by Atlassian Jira
(v8.20.10#820010)