[ 
https://issues.apache.org/jira/browse/CAMEL-24131?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Claus Ibsen resolved CAMEL-24131.
---------------------------------
    Resolution: Fixed

> 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)

Reply via email to