Federico Mariani created CAMEL-24129:
----------------------------------------
Summary: camel-jpa: JpaConsumer ignores the configured
preDeleteHandler and re-derives it via reflection on every message
Key: CAMEL-24129
URL: https://issues.apache.org/jira/browse/CAMEL-24129
Project: Camel
Issue Type: Bug
Components: camel-jpa
Reporter: Federico Mariani
h3. Problem
{{JpaConsumer.processBatch()}} (JpaConsumer.java:199) calls:
{code:java}
createPreDeleteHandler().deleteObject(batchEntityManager, result, exchange);
{code}
instead of the cached accessor {{getPreDeleteHandler()}}
(JpaConsumer.java:259-264), which lazily creates and *caches* the handler:
{code:java}
public DeleteHandler<Object> getPreDeleteHandler() {
if (preDeleteHandler == null) {
preDeleteHandler = createPreDeleteHandler();
}
return preDeleteHandler;
}
{code}
The {{@Consumed}} counterpart a few lines below (line 215) does it correctly
via {{getDeleteHandler()}}.
h3. Impact
# A user-supplied {{preDeleteHandler}} (the {{@UriParam(label = "consumer")}}
option wired in {{JpaEndpoint.createConsumer()}}, JpaEndpoint.java:97-98/160)
is *never invoked* -- {{createPreDeleteHandler()}} always re-derives the
handler from the {{@PreConsumed}} annotation scan on the entity class (or falls
back to the no-op default), completely bypassing anything set via
{{setPreDeleteHandler}} / the {{preDeleteHandler}} URI option.
# {{createPreDeleteHandler()}} runs
{{AnnotationHelper.findMethodsWithAnnotation(entityType, PreConsumed.class)}}
-- a reflective scan of the entity's methods -- for *every entity of every poll
batch*, instead of once per consumer lifetime.
h3. How to reproduce
Configure a route with a custom {{preDeleteHandler}}:
{code:java}
JpaEndpoint endpoint = ...;
endpoint.setPreDeleteHandler((em, entityBean, exchange) -> called.set(true));
{code}
and observe that {{called}} is never set to {{true}} even though the row is
consumed normally, because {{processBatch}} never calls
{{getPreDeleteHandler()}}.
h3. Suggested fix
Change line 199 to call {{getPreDeleteHandler()}} instead of
{{createPreDeleteHandler()}}, mirroring the
{{@Consumed}}/{{getDeleteHandler()}} pattern already used a few lines below.
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)