Federico Mariani created CAMEL-24131:
----------------------------------------
Summary: 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
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)